@spfn/auth 0.3.0-beta.6 → 0.3.0-beta.8

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/server.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { A as AuthInitOptions, n as OAuthProvider, k as VerificationPurpose, i as PermissionCategory, o as AuthContext } from './authenticate-98lBIMxP.js';
2
- export { p as AuthProfileOutcome, q as AuthProfileVerifier, r as ChangePasswordParams, s as CompleteSignupParams, t as ConfirmSignupLinkParams, C as ConfirmSignupLinkResult, D as DeviceNameSchema, E as EmailSchema, I as IssueOneTimeTokenResult, u as KEY_FINGERPRINT_PREFIX_LENGTH, K as KeySummary, v as LoginParams, L as LoginResult, w as LogoutParams, N as NativeVerifyOptions, x as NormalizedIdentity, y as OAuthCallbackParams, z as OAuthCallbackResult, B as OAuthCodeExchangeOptions, F as OAuthNativeParams, e as OAuthNativeResult, G as OAuthStartParams, O as OAuthStartResult, H as OAuthTokens, J as PasswordSchema, M as PhoneSchema, Q as PlatformSchema, T as RegisterParams, W as RegisterPublicKeyParams, a as RegisterResult, X as RequestSignupLinkParams, b as RequestSignupLinkResult, Y as RevokeAllKeysParams, d as RevokeAllKeysResult, Z as RevokeKeyParams, _ as RotateKeyParams, c as RotateKeyResult, $ as SendVerificationCodeParams, S as SendVerificationCodeResult, a0 as TargetTypeSchema, a1 as UnlinkNotification, a2 as UnlinkNotifyRejection, a3 as UnlinkNotifyRequest, a4 as UnlinkNotifyResult, V as VERIFICATION_PURPOSES, j as VERIFICATION_TARGET_TYPES, a5 as VerificationPurposeSchema, l as VerificationTargetType, a6 as VerifyCodeParams, a7 as VerifyCodeResult, m as authRouter, a8 as authenticate, a9 as buildOAuthErrorUrl, aa as changePasswordService, ab as completeSignupService, ac as confirmSignupLinkService, ad as getEnabledOAuthProviders, ae as getGoogleAccessToken, af as getOAuthProvider, ag as getRegisteredProviders, ah as isOAuthProviderEnabled, ai as isSafeReturnPath, aj as issueOneTimeTokenService, ak as listKeysService, al as loginService, am as logoutService, an as oauthCallbackService, ao as oauthNativeService, ap as oauthStartService, aq as oauthUnlinkNotifyService, ar as optionalAuth, as as registerOAuthProvider, at as registerPublicKeyService, au as registerService, av as requestSignupLinkService, aw as requireEnabledProvider, ax as resolveAuthenticatedUser, ay as revokeAllKeysService, az as revokeKeyService, aA as rotateKeyService, aB as runAuthProfile, aC as selectAuthProfile, aD as sendVerificationCodeService, aE as verifyCodeService, aF as verifyOneTimeTokenService } from './authenticate-98lBIMxP.js';
1
+ import { A as AuthInitOptions, o as OAuthProvider, l as VerificationPurpose, j as PermissionCategory, p as AuthContext } from './machine-principals-Bd5hp76H.js';
2
+ export { q as ApproveDeviceAuthParams, r as AuthProfileOutcome, s as AuthProfileVerifier, t as ChangePasswordParams, u as CompleteSignupParams, v as ConfirmSignupLinkParams, C as ConfirmSignupLinkResult, w as DenyDeviceAuthParams, x as DeviceAuthApprovedResult, y as DeviceAuthInfoParams, D as DeviceAuthInfoResult, z as DeviceAuthPendingResult, B as DeviceAuthPollResponseSchema, E as DeviceNameSchema, F as EmailSchema, G as FingerprintSchema, I as IssueOneTimeTokenResult, H as KEY_FINGERPRINT_PREFIX_LENGTH, J as KeyIdSchema, K as KeySummary, M as LoginParams, L as LoginResult, N as LogoutParams, Q as MachinePrincipal, T as MachineVerifierRegistration, W as NativeVerifyOptions, X as NormalizedIdentity, Y as OAuthCallbackParams, Z as OAuthCallbackResult, _ as OAuthCodeExchangeOptions, $ as OAuthNativeParams, f as OAuthNativeResult, a0 as OAuthStartParams, O as OAuthStartResult, a1 as OAuthTokens, a2 as PasswordSchema, a3 as PhoneSchema, a4 as PlatformSchema, a5 as PollDeviceAuthParams, a6 as PollDeviceAuthResult, a7 as PublicKeySchema, a8 as RegisterParams, a9 as RegisterPublicKeyParams, a as RegisterResult, aa as RequestSignupLinkParams, b as RequestSignupLinkResult, ab as RevokeAllKeysParams, e as RevokeAllKeysResult, ac as RevokeKeyParams, ad as RotateKeyParams, d as RotateKeyResult, ae as SendVerificationCodeParams, S as SendVerificationCodeResult, af as StartDeviceAuthParams, c as StartDeviceAuthResult, ag as TargetTypeSchema, ah as UnlinkNotification, ai as UnlinkNotifyRejection, aj as UnlinkNotifyRequest, ak as UnlinkNotifyResult, al as UserCodeSchema, V as VERIFICATION_PURPOSES, k as VERIFICATION_TARGET_TYPES, am as VerificationPurposeSchema, n as VerificationTargetType, an as VerifyCodeParams, ao as VerifyCodeResult, ap as approveDeviceAuthService, m as authRouter, aq as authenticate, ar as buildOAuthErrorUrl, as as changePasswordService, at as completeSignupService, au as confirmSignupLinkService, av as denyDeviceAuthService, aw as getDeviceAuthInfoService, ax as getEnabledOAuthProviders, ay as getGoogleAccessToken, az as getMachinePrincipal, aA as getOAuthProvider, aB as getRegisteredProviders, aC as isOAuthProviderEnabled, aD as isSafeReturnPath, aE as issueOneTimeTokenService, aF as listKeysService, aG as loginService, aH as logoutService, aI as machineAuth, aJ as oauthCallbackService, aK as oauthNativeService, aL as oauthStartService, aM as oauthUnlinkNotifyService, aN as optionalAuth, aO as pollDeviceAuthService, aP as registerAuthProfile, aQ as registerMachineVerifier, aR as registerOAuthProvider, aS as registerPublicKeyService, aT as registerService, aU as requestSignupLinkService, aV as requireEnabledProvider, aW as requireMachineScope, aX as resolveAuthenticatedUser, aY as revokeAllKeysService, aZ as revokeKeyService, a_ as rotateKeyService, a$ as runAuthProfile, b0 as selectAuthProfile, b1 as sendVerificationCodeService, b2 as startDeviceAuthService, b3 as verifyCodeService, b4 as verifyOneTimeTokenService } from './machine-principals-Bd5hp76H.js';
3
3
  import * as drizzle_orm_pg_core from 'drizzle-orm/pg-core';
4
4
  import { K as KeyAlgorithmType, d as InvitationStatus, j as SocialProvider, c as AccountDeletionRequestedBy, i as PurgeStrategy } from './types-DYyhze28.js';
5
5
  export { A as ACCOUNT_DELETION_REQUESTED_BY, a as ACCOUNT_DELETION_REQUEST_STATUSES, b as AccountDeletionRequestStatus, I as INVITATION_STATUSES, e as KEY_ALGORITHM, f as KEY_DEVICE_NAME_MAX_LENGTH, g as KEY_PLATFORM, h as KeyPlatformType, P as PURGE_STRATEGIES, S as SOCIAL_PROVIDERS, U as USER_STATUSES, k as UserStatus } from './types-DYyhze28.js';
@@ -3296,6 +3296,288 @@ declare const signupLinkTokens: drizzle_orm_pg_core.PgTableWithColumns<{
3296
3296
  type SignupLinkToken = typeof signupLinkTokens.$inferSelect;
3297
3297
  type NewSignupLinkToken = typeof signupLinkTokens.$inferInsert;
3298
3298
 
3299
+ /**
3300
+ * @spfn/auth - Device Authorizations Entity
3301
+ *
3302
+ * Backs device-code login: a device with no key on file yet parks its public key
3303
+ * here, shows a short code, and an already-authenticated device approves it. The
3304
+ * parked key is registered against the approving user's account when the waiting
3305
+ * device polls.
3306
+ *
3307
+ * The pending key material duplicates the `user_public_keys` columns rather than
3308
+ * writing a row there early. A key in `user_public_keys` can sign requests, and
3309
+ * nothing about a row here has been approved yet — one table means "registered"
3310
+ * and the other means "asked to be", and neither is a state of the other.
3311
+ *
3312
+ * Nothing sweeps this table. Rows are judged by `expiresAt` on read, so a stale
3313
+ * row cannot authorize anything; it only keeps its user code out of circulation,
3314
+ * and 31^8 codes do not run out.
3315
+ */
3316
+ /**
3317
+ * Lifecycle of one device-code request.
3318
+ *
3319
+ * Every transition is one-way and the two terminal states differ: `denied` is a
3320
+ * refusal the waiting device is told about, `consumed` is a completed login that
3321
+ * answers as if it never existed. `pending -> approved -> consumed` is the only
3322
+ * path to a registered key.
3323
+ *
3324
+ * `denied` is also where a global revocation puts a record — a revoke-all, a
3325
+ * password change, a deletion request — including one already approved. The
3326
+ * account has withdrawn it, and what the waiting device is owed for that is the
3327
+ * answer a refusal gives.
3328
+ */
3329
+ declare const DEVICE_AUTH_STATUSES: readonly ["pending", "approved", "denied", "consumed"];
3330
+ type DeviceAuthStatus = typeof DEVICE_AUTH_STATUSES[number];
3331
+ declare const deviceAuthorizations: drizzle_orm_pg_core.PgTableWithColumns<{
3332
+ name: "device_authorizations";
3333
+ schema: string;
3334
+ columns: {
3335
+ createdAt: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>, {
3336
+ name: string;
3337
+ tableName: "device_authorizations";
3338
+ dataType: "object date";
3339
+ data: Date;
3340
+ driverParam: string;
3341
+ notNull: true;
3342
+ hasDefault: true;
3343
+ isPrimaryKey: false;
3344
+ isAutoincrement: false;
3345
+ hasRuntimeDefault: false;
3346
+ enumValues: undefined;
3347
+ identity: undefined;
3348
+ generated: undefined;
3349
+ }>;
3350
+ updatedAt: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.PgTimestampBuilder>>>, {
3351
+ name: string;
3352
+ tableName: "device_authorizations";
3353
+ dataType: "object date";
3354
+ data: Date;
3355
+ driverParam: string;
3356
+ notNull: true;
3357
+ hasDefault: true;
3358
+ isPrimaryKey: false;
3359
+ isAutoincrement: false;
3360
+ hasRuntimeDefault: false;
3361
+ enumValues: undefined;
3362
+ identity: undefined;
3363
+ generated: undefined;
3364
+ }>;
3365
+ id: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetIsPrimaryKey<drizzle_orm_pg_core.PgBigSerial53Builder>, {
3366
+ name: string;
3367
+ tableName: "device_authorizations";
3368
+ dataType: "number int53";
3369
+ data: number;
3370
+ driverParam: number;
3371
+ notNull: true;
3372
+ hasDefault: true;
3373
+ isPrimaryKey: false;
3374
+ isAutoincrement: false;
3375
+ hasRuntimeDefault: false;
3376
+ enumValues: undefined;
3377
+ identity: undefined;
3378
+ generated: undefined;
3379
+ }>;
3380
+ deviceCodeHash: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
3381
+ name: string;
3382
+ tableName: "device_authorizations";
3383
+ dataType: "string";
3384
+ data: string;
3385
+ driverParam: string;
3386
+ notNull: true;
3387
+ hasDefault: false;
3388
+ isPrimaryKey: false;
3389
+ isAutoincrement: false;
3390
+ hasRuntimeDefault: false;
3391
+ enumValues: undefined;
3392
+ identity: undefined;
3393
+ generated: undefined;
3394
+ }>;
3395
+ userCode: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
3396
+ name: string;
3397
+ tableName: "device_authorizations";
3398
+ dataType: "string";
3399
+ data: string;
3400
+ driverParam: string;
3401
+ notNull: true;
3402
+ hasDefault: false;
3403
+ isPrimaryKey: false;
3404
+ isAutoincrement: false;
3405
+ hasRuntimeDefault: false;
3406
+ enumValues: undefined;
3407
+ identity: undefined;
3408
+ generated: undefined;
3409
+ }>;
3410
+ publicKey: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
3411
+ name: string;
3412
+ tableName: "device_authorizations";
3413
+ dataType: "string";
3414
+ data: string;
3415
+ driverParam: string;
3416
+ notNull: true;
3417
+ hasDefault: false;
3418
+ isPrimaryKey: false;
3419
+ isAutoincrement: false;
3420
+ hasRuntimeDefault: false;
3421
+ enumValues: undefined;
3422
+ identity: undefined;
3423
+ generated: undefined;
3424
+ }>;
3425
+ keyId: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
3426
+ name: string;
3427
+ tableName: "device_authorizations";
3428
+ dataType: "string";
3429
+ data: string;
3430
+ driverParam: string;
3431
+ notNull: true;
3432
+ hasDefault: false;
3433
+ isPrimaryKey: false;
3434
+ isAutoincrement: false;
3435
+ hasRuntimeDefault: false;
3436
+ enumValues: undefined;
3437
+ identity: undefined;
3438
+ generated: undefined;
3439
+ }>;
3440
+ fingerprint: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>>, {
3441
+ name: string;
3442
+ tableName: "device_authorizations";
3443
+ dataType: "string";
3444
+ data: string;
3445
+ driverParam: string;
3446
+ notNull: true;
3447
+ hasDefault: false;
3448
+ isPrimaryKey: false;
3449
+ isAutoincrement: false;
3450
+ hasRuntimeDefault: false;
3451
+ enumValues: undefined;
3452
+ identity: undefined;
3453
+ generated: undefined;
3454
+ }>;
3455
+ algorithm: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<["ES256", "RS256"] & [string, ...string[]]>>>, {
3456
+ name: string;
3457
+ tableName: "device_authorizations";
3458
+ dataType: "string enum";
3459
+ data: "ES256" | "RS256";
3460
+ driverParam: string;
3461
+ notNull: true;
3462
+ hasDefault: true;
3463
+ isPrimaryKey: false;
3464
+ isAutoincrement: false;
3465
+ hasRuntimeDefault: false;
3466
+ enumValues: ["ES256", "RS256"] & [string, ...string[]];
3467
+ identity: undefined;
3468
+ generated: undefined;
3469
+ }>;
3470
+ deviceName: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.PgTextBuilder<[string, ...string[]]>, {
3471
+ name: string;
3472
+ tableName: "device_authorizations";
3473
+ dataType: "string";
3474
+ data: string;
3475
+ driverParam: string;
3476
+ notNull: false;
3477
+ hasDefault: false;
3478
+ isPrimaryKey: false;
3479
+ isAutoincrement: false;
3480
+ hasRuntimeDefault: false;
3481
+ enumValues: undefined;
3482
+ identity: undefined;
3483
+ generated: undefined;
3484
+ }>;
3485
+ platform: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.PgTextBuilder<["ios", "android", "web", "desktop"] & [string, ...string[]]>, {
3486
+ name: string;
3487
+ tableName: "device_authorizations";
3488
+ dataType: "string enum";
3489
+ data: "ios" | "android" | "web" | "desktop";
3490
+ driverParam: string;
3491
+ notNull: false;
3492
+ hasDefault: false;
3493
+ isPrimaryKey: false;
3494
+ isAutoincrement: false;
3495
+ hasRuntimeDefault: false;
3496
+ enumValues: ["ios", "android", "web", "desktop"] & [string, ...string[]];
3497
+ identity: undefined;
3498
+ generated: undefined;
3499
+ }>;
3500
+ status: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetHasDefault<drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTextBuilder<["pending", "approved", "denied", "consumed"] & [string, ...string[]]>>>, {
3501
+ name: string;
3502
+ tableName: "device_authorizations";
3503
+ dataType: "string enum";
3504
+ data: "pending" | "approved" | "denied" | "consumed";
3505
+ driverParam: string;
3506
+ notNull: true;
3507
+ hasDefault: true;
3508
+ isPrimaryKey: false;
3509
+ isAutoincrement: false;
3510
+ hasRuntimeDefault: false;
3511
+ enumValues: ["pending", "approved", "denied", "consumed"] & [string, ...string[]];
3512
+ identity: undefined;
3513
+ generated: undefined;
3514
+ }>;
3515
+ userId: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.PgBigInt53Builder, {
3516
+ name: string;
3517
+ tableName: "device_authorizations";
3518
+ dataType: "number int53";
3519
+ data: number;
3520
+ driverParam: string | number;
3521
+ notNull: false;
3522
+ hasDefault: false;
3523
+ isPrimaryKey: false;
3524
+ isAutoincrement: false;
3525
+ hasRuntimeDefault: false;
3526
+ enumValues: undefined;
3527
+ identity: undefined;
3528
+ generated: undefined;
3529
+ }>;
3530
+ expiresAt: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.SetNotNull<drizzle_orm_pg_core.PgTimestampBuilder>, {
3531
+ name: string;
3532
+ tableName: "device_authorizations";
3533
+ dataType: "object date";
3534
+ data: Date;
3535
+ driverParam: string;
3536
+ notNull: true;
3537
+ hasDefault: false;
3538
+ isPrimaryKey: false;
3539
+ isAutoincrement: false;
3540
+ hasRuntimeDefault: false;
3541
+ enumValues: undefined;
3542
+ identity: undefined;
3543
+ generated: undefined;
3544
+ }>;
3545
+ approvedAt: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.PgTimestampBuilder, {
3546
+ name: string;
3547
+ tableName: "device_authorizations";
3548
+ dataType: "object date";
3549
+ data: Date;
3550
+ driverParam: string;
3551
+ notNull: false;
3552
+ hasDefault: false;
3553
+ isPrimaryKey: false;
3554
+ isAutoincrement: false;
3555
+ hasRuntimeDefault: false;
3556
+ enumValues: undefined;
3557
+ identity: undefined;
3558
+ generated: undefined;
3559
+ }>;
3560
+ consumedAt: drizzle_orm_pg_core.PgBuildColumn<"device_authorizations", drizzle_orm_pg_core.PgTimestampBuilder, {
3561
+ name: string;
3562
+ tableName: "device_authorizations";
3563
+ dataType: "object date";
3564
+ data: Date;
3565
+ driverParam: string;
3566
+ notNull: false;
3567
+ hasDefault: false;
3568
+ isPrimaryKey: false;
3569
+ isAutoincrement: false;
3570
+ hasRuntimeDefault: false;
3571
+ enumValues: undefined;
3572
+ identity: undefined;
3573
+ generated: undefined;
3574
+ }>;
3575
+ };
3576
+ dialect: "pg";
3577
+ }>;
3578
+ type DeviceAuthorization = typeof deviceAuthorizations.$inferSelect;
3579
+ type NewDeviceAuthorization = typeof deviceAuthorizations.$inferInsert;
3580
+
3299
3581
  /**
3300
3582
  * @spfn/auth - Permissions Entity
3301
3583
  *
@@ -4026,15 +4308,15 @@ declare class UsersRepository extends BaseRepository {
4026
4308
  create(data: NewUser): Promise<{
4027
4309
  email: string | null;
4028
4310
  phone: string | null;
4029
- id: number;
4311
+ status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
4030
4312
  publicId: string;
4313
+ passwordChangeRequired: boolean;
4314
+ id: number;
4031
4315
  username: string | null;
4032
4316
  passwordHash: string | null;
4033
- passwordChangeRequired: boolean;
4034
4317
  roleId: number;
4035
4318
  createdAt: Date;
4036
4319
  updatedAt: Date;
4037
- status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
4038
4320
  emailVerifiedAt: Date | null;
4039
4321
  phoneVerifiedAt: Date | null;
4040
4322
  lastLoginAt: Date | null;
@@ -4186,15 +4468,15 @@ declare class UsersRepository extends BaseRepository {
4186
4468
  deleteById(id: number): Promise<{
4187
4469
  email: string | null;
4188
4470
  phone: string | null;
4189
- id: number;
4471
+ status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
4190
4472
  publicId: string;
4473
+ passwordChangeRequired: boolean;
4474
+ id: number;
4191
4475
  username: string | null;
4192
4476
  passwordHash: string | null;
4193
- passwordChangeRequired: boolean;
4194
4477
  roleId: number;
4195
4478
  createdAt: Date;
4196
4479
  updatedAt: Date;
4197
- status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
4198
4480
  emailVerifiedAt: Date | null;
4199
4481
  phoneVerifiedAt: Date | null;
4200
4482
  lastLoginAt: Date | null;
@@ -4813,6 +5095,118 @@ declare class SignupLinkTokensRepository extends BaseRepository {
4813
5095
  }
4814
5096
  declare const signupLinkTokensRepository: SignupLinkTokensRepository;
4815
5097
 
5098
+ /**
5099
+ * Device Authorizations Repository
5100
+ *
5101
+ * Data access for device-code login. Extends BaseRepository for transaction
5102
+ * context detection and read/write splitting.
5103
+ *
5104
+ * Every state change here is a conditional UPDATE naming the exact state it is
5105
+ * allowed to move from, returning the row only when THIS call was the one that
5106
+ * moved it. That is what makes the operations safe to race: two polls on one
5107
+ * approved record, or a deny arriving while an approve is in flight, produce one
5108
+ * winner and one refusal instead of both callers acting on a row they each read
5109
+ * as still theirs to move. Read-then-write would lose that.
5110
+ *
5111
+ * Each of those transitions also carries the TTL, as `now()` evaluated by the
5112
+ * database. The service reads a record before it acts on it, and a record can
5113
+ * pass its expiry in the gap between that read and this UPDATE — an approved one
5114
+ * most of all, since the poll that spends it is the one call that registers a
5115
+ * key. Judging the clock only in the read would let that key be registered after
5116
+ * the code was dead.
5117
+ */
5118
+
5119
+ declare class DeviceAuthorizationsRepository extends BaseRepository {
5120
+ /**
5121
+ * Insert a pending authorization, unless one of its codes is already taken.
5122
+ *
5123
+ * `onConflictDoNothing` rather than letting the unique index raise: the start
5124
+ * route runs inside a transaction, and a raised unique violation aborts it,
5125
+ * so the retry that a generated-code collision calls for could not run — every
5126
+ * statement after it would fail with "current transaction is aborted" instead.
5127
+ * An empty result is the collision signal, and the caller draws a fresh code.
5128
+ *
5129
+ * Write primary.
5130
+ *
5131
+ * @returns the inserted row, or null if either code collided
5132
+ */
5133
+ create(data: NewDeviceAuthorization): Promise<DeviceAuthorization | null>;
5134
+ /**
5135
+ * Find a record by its normalized user code, in any state.
5136
+ *
5137
+ * Deliberately unfiltered: which refusal a caller is owed — expired, already
5138
+ * handled, unknown — is the service's decision, and a row filtered out here
5139
+ * would be indistinguishable from a code that was never issued.
5140
+ *
5141
+ * Read replica.
5142
+ */
5143
+ findByUserCode(userCode: string): Promise<DeviceAuthorization | null>;
5144
+ /**
5145
+ * Find a record by the hash of a device code, in any state.
5146
+ * Unfiltered for the same reason as `findByUserCode`.
5147
+ *
5148
+ * Read replica.
5149
+ */
5150
+ findByDeviceCodeHash(deviceCodeHash: string): Promise<DeviceAuthorization | null>;
5151
+ /**
5152
+ * Bind the approving user and move the record to `approved`, but only from
5153
+ * `pending`.
5154
+ *
5155
+ * `userId` comes from the approver's authenticated session — never from a
5156
+ * request body — so this is the point where the record gains an owner.
5157
+ *
5158
+ * @returns the updated row, or null if it was no longer pending, or expired
5159
+ */
5160
+ approve(id: number, userId: number): Promise<DeviceAuthorization | null>;
5161
+ /**
5162
+ * Move the record to `denied`, but only from `pending`.
5163
+ *
5164
+ * No user is bound: a refusal should leave no record of who was asked.
5165
+ *
5166
+ * @returns the updated row, or null if it was no longer pending, or expired
5167
+ */
5168
+ deny(id: number): Promise<DeviceAuthorization | null>;
5169
+ /**
5170
+ * Refuse every authorization a user still has in flight.
5171
+ *
5172
+ * This is the device-code half of a global revocation. Revoking
5173
+ * `user_public_keys` alone leaves an approved-but-uncollected record behind,
5174
+ * and the next poll on it registers a brand-new active key — so "sign every
5175
+ * device out" would hand one straight back to whoever was still waiting,
5176
+ * which is exactly the person a revoke-all is usually aimed at.
5177
+ *
5178
+ * `denied` rather than a status of its own: a swept record owes its holder
5179
+ * the answer a refused one owes, on all four operations — the waiting device
5180
+ * is told no and stops polling, and info/approve/deny say the request was
5181
+ * already answered. Adding a fourth live status would add a migration and a
5182
+ * case-table row to record a distinction nothing acts on.
5183
+ *
5184
+ * Expired rows are swept too. A global revoke is not the place to reason
5185
+ * about which dead rows were about to die anyway.
5186
+ *
5187
+ * `pending` alongside `approved` even though a pending row carries no
5188
+ * `userId` today, so only approved rows can match: the state list says which
5189
+ * states this is meant to close, and a later change that binds the user
5190
+ * earlier should not silently reopen the hole.
5191
+ *
5192
+ * @returns the rows this call refused
5193
+ */
5194
+ denyAllActiveByUserId(userId: number): Promise<DeviceAuthorization[]>;
5195
+ /**
5196
+ * Spend an approved record, but only from `approved`, and address it by the
5197
+ * device code hash the caller actually presented.
5198
+ *
5199
+ * This is the one-shot: the winner of two concurrent polls registers the key,
5200
+ * and the loser sees no approved record and is answered as if the code were
5201
+ * unknown. Matching on the hash rather than on an id read a moment ago keeps
5202
+ * the whole decision in one statement.
5203
+ *
5204
+ * @returns the spent row, or null if it was not approved (any more), or expired
5205
+ */
5206
+ consumeApproved(deviceCodeHash: string): Promise<DeviceAuthorization | null>;
5207
+ }
5208
+ declare const deviceAuthorizationsRepository: DeviceAuthorizationsRepository;
5209
+
4816
5210
  /**
4817
5211
  * Roles Repository
4818
5212
  *
@@ -5531,11 +5925,11 @@ declare class InvitationsRepository extends BaseRepository {
5531
5925
  email: string;
5532
5926
  metadata: Record<string, any> | null;
5533
5927
  token: string;
5928
+ status: "pending" | "accepted" | "expired" | "cancelled";
5534
5929
  id: number;
5535
5930
  roleId: number;
5536
5931
  createdAt: Date;
5537
5932
  updatedAt: Date;
5538
- status: "pending" | "accepted" | "expired" | "cancelled";
5539
5933
  invitedBy: number;
5540
5934
  expiresAt: Date;
5541
5935
  acceptedAt: Date | null;
@@ -5565,11 +5959,11 @@ declare class InvitationsRepository extends BaseRepository {
5565
5959
  email: string;
5566
5960
  metadata: Record<string, any> | null;
5567
5961
  token: string;
5962
+ status: "pending" | "accepted" | "expired" | "cancelled";
5568
5963
  id: number;
5569
5964
  roleId: number;
5570
5965
  createdAt: Date;
5571
5966
  updatedAt: Date;
5572
- status: "pending" | "accepted" | "expired" | "cancelled";
5573
5967
  invitedBy: number;
5574
5968
  expiresAt: Date;
5575
5969
  acceptedAt: Date | null;
@@ -5958,11 +6352,11 @@ declare class AccountDeletionRequestsRepository extends BaseRepository {
5958
6352
  * Write primary 사용
5959
6353
  */
5960
6354
  create(data: NewAccountDeletionRequest): Promise<{
6355
+ status: "pending" | "cancelled" | "completed";
5961
6356
  userId: number | null;
5962
6357
  id: number;
5963
6358
  createdAt: Date;
5964
6359
  updatedAt: Date;
5965
- status: "pending" | "cancelled" | "completed";
5966
6360
  reason: string | null;
5967
6361
  purgeScheduledAt: Date;
5968
6362
  cancelledAt: Date | null;
@@ -6552,15 +6946,15 @@ declare function getUser(c: Context | {
6552
6946
  }): {
6553
6947
  email: string | null;
6554
6948
  phone: string | null;
6555
- id: number;
6949
+ status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
6556
6950
  publicId: string;
6951
+ passwordChangeRequired: boolean;
6952
+ id: number;
6557
6953
  username: string | null;
6558
6954
  passwordHash: string | null;
6559
- passwordChangeRequired: boolean;
6560
6955
  roleId: number;
6561
6956
  createdAt: Date;
6562
6957
  updatedAt: Date;
6563
- status: "active" | "inactive" | "suspended" | "pending_deletion" | "deleted";
6564
6958
  emailVerifiedAt: Date | null;
6565
6959
  phoneVerifiedAt: Date | null;
6566
6960
  lastLoginAt: Date | null;
@@ -6651,6 +7045,8 @@ declare const COOKIE_NAMES: {
6651
7045
  readonly OAUTH_CSRF: string;
6652
7046
  /** Password-setup session for verified-email signup — temporary, single-purpose */
6653
7047
  readonly SIGNUP_SETUP: string;
7048
+ /** CSRF token — the only cookie here the browser can read */
7049
+ readonly CSRF: string;
6654
7050
  };
6655
7051
  /**
6656
7052
  * OAuth CSRF 쿠키를 PORT 접미사와 무관하게 전부 수집한다.
@@ -6712,6 +7108,36 @@ interface BeforeRegisterContext {
6712
7108
  /** App-supplied registration metadata (register params / OAuth start params / invitation) */
6713
7109
  metadata?: Record<string, unknown>;
6714
7110
  }
7111
+ /**
7112
+ * How the Next.js proxy treats a cookie-authenticated mutation that arrives
7113
+ * without a valid CSRF header.
7114
+ *
7115
+ * - `off`: no check
7116
+ * - `warn`: allow it through, log one line per request that would be refused
7117
+ * - `enforce`: refuse it with 403
7118
+ */
7119
+ type CsrfMode = 'off' | 'warn' | 'enforce';
7120
+ /**
7121
+ * CSRF configuration for the Next.js proxy
7122
+ */
7123
+ interface AuthCsrfConfig {
7124
+ /**
7125
+ * @default 'warn' — an existing app gets signal before it gets breakage.
7126
+ * `SPFN_AUTH_CSRF` sets it when this is not; new apps scaffolded by
7127
+ * `spfn init` are given `enforce`.
7128
+ */
7129
+ mode?: CsrfMode;
7130
+ /**
7131
+ * Backend paths that skip the check, matched exactly.
7132
+ *
7133
+ * These are route paths as the backend sees them (`/webhooks/stripe`), not
7134
+ * `/api/rpc/...` URLs, with route params already substituted. Intended for
7135
+ * endpoints a browser session never calls — webhook receivers and the like.
7136
+ * A path listed here is unprotected for cookie callers too, so list only
7137
+ * endpoints that carry their own authentication.
7138
+ */
7139
+ exemptPaths?: string[];
7140
+ }
6715
7141
  /**
6716
7142
  * Auth configuration
6717
7143
  */
@@ -6755,6 +7181,17 @@ interface AuthConfig {
6755
7181
  * ```
6756
7182
  */
6757
7183
  beforeRegister?: (context: BeforeRegisterContext) => void | Promise<void>;
7184
+ /**
7185
+ * CSRF protection for cookie-session mutations, enforced in the Next.js proxy.
7186
+ *
7187
+ * @example
7188
+ * ```typescript
7189
+ * configureAuth({
7190
+ * csrf: { mode: 'enforce', exemptPaths: ['/webhooks/stripe'] },
7191
+ * });
7192
+ * ```
7193
+ */
7194
+ csrf?: AuthCsrfConfig;
6758
7195
  }
6759
7196
  /**
6760
7197
  * Configure global auth settings
@@ -6796,6 +7233,64 @@ declare function runBeforeRegister(context: BeforeRegisterContext): Promise<void
6796
7233
  * 4. Default (7 days)
6797
7234
  */
6798
7235
  declare function getSessionTtl(override?: string | number): number;
7236
+ /**
7237
+ * Get the CSRF mode
7238
+ *
7239
+ * Priority:
7240
+ * 1. Global config (configureAuth)
7241
+ * 2. Environment variable (SPFN_AUTH_CSRF)
7242
+ * 3. Default ('warn')
7243
+ *
7244
+ * An unrecognized value is a typo in the one setting that turns the check on;
7245
+ * it resolves to `enforce` and says so, rather than quietly leaving mutations
7246
+ * unprotected. It says so once per process: this runs on every mutation, so a
7247
+ * per-call error would be pure repetition burying the rest of the log.
7248
+ */
7249
+ declare function getCsrfMode(): CsrfMode;
7250
+ /**
7251
+ * Get the paths exempted from the CSRF check (exact match, backend route paths)
7252
+ */
7253
+ declare function getCsrfExemptPaths(): string[];
7254
+
7255
+ /**
7256
+ * @spfn/auth - CSRF token derivation
7257
+ *
7258
+ * The token is an HMAC of the session's key id under a subkey derived from the
7259
+ * session secret. Two properties follow from that shape:
7260
+ *
7261
+ * - The proxy recomputes it from the session it just unsealed, so a value an
7262
+ * attacker planted in the readable cookie (sibling-subdomain cookie tossing)
7263
+ * never verifies. Nothing here compares a cookie against a header.
7264
+ * - It is bound to the key id, so rotating the session key invalidates it.
7265
+ *
7266
+ * No new secret: the subkey is a labelled HMAC of SPFN_AUTH_SESSION_SECRET, so
7267
+ * the key that encrypts sessions is never used verbatim as the token key.
7268
+ */
7269
+ /** Header the readable CSRF cookie is mirrored into by the client. */
7270
+ declare const CSRF_HEADER = "x-spfn-csrf";
7271
+ /**
7272
+ * Derive the CSRF token for a session key id.
7273
+ *
7274
+ * @param keyId - Session key id (`SessionData.keyId`)
7275
+ * @returns 64-char hex token — safe to put in a readable cookie, it reveals
7276
+ * neither the secret nor the key id
7277
+ */
7278
+ declare function deriveCsrfToken(keyId: string): Promise<string>;
7279
+ /**
7280
+ * Whether a presented header value carries the expected token.
7281
+ *
7282
+ * The header may carry several comma-separated candidates — a browser sees every
7283
+ * `spfn_csrf*` cookie set on the host and cannot tell which dev instance owns
7284
+ * which, nor which of two same-named cookies a sibling subdomain tossed in.
7285
+ *
7286
+ * Every candidate the client is allowed to send is checked — the cap here is the
7287
+ * one it selects against — so a genuine value is never evicted by tossed ones
7288
+ * that happen to sort ahead of it. A header longer than that can only come from a
7289
+ * client that ignored the shared bound, and its surplus is dropped. Accepting any
7290
+ * match is no weaker than accepting one: a candidate the attacker chose still has
7291
+ * to equal a value recomputed from the session.
7292
+ */
7293
+ declare function matchesCsrfToken(expected: string, presented: string | null | undefined): boolean;
6799
7294
 
6800
7295
  /**
6801
7296
  * One-Time Token Manager
@@ -6898,6 +7393,107 @@ declare function configureDeletion(options?: Partial<AuthDeletionConfig>): void;
6898
7393
  */
6899
7394
  declare function getDeletionConfig(): AuthDeletionConfig;
6900
7395
 
7396
+ /**
7397
+ * Device-code Login Configuration
7398
+ *
7399
+ * Singleton config for device-code login, mirroring `lib/deletion-config.ts`: a
7400
+ * mutable module-level value, set once during `createAuthLifecycle()` and read at
7401
+ * request time.
7402
+ *
7403
+ * Both knobs are answers the server hands to a client that cannot ask again — the
7404
+ * waiting device is told its expiry and its poll interval in the `start` response
7405
+ * and then just obeys them — so they have to be resolved before any request is
7406
+ * served, not read from an environment variable at each use.
7407
+ */
7408
+ interface AuthDeviceAuthConfig {
7409
+ /** How long a device code stays usable, in milliseconds. */
7410
+ ttlMs: number;
7411
+ /** How long the waiting device should wait between polls, in milliseconds. */
7412
+ intervalMs: number;
7413
+ }
7414
+ /**
7415
+ * Ten minutes. Long enough to walk to the other device and type the code, short
7416
+ * enough that a code glimpsed over a shoulder is worthless soon after.
7417
+ */
7418
+ declare const DEFAULT_DEVICE_AUTH_TTL_MS: number;
7419
+ /** Five seconds. The interval the server asks for; the rate limit is what enforces it. */
7420
+ declare const DEFAULT_DEVICE_AUTH_INTERVAL_MS: number;
7421
+ /**
7422
+ * Set the resolved device-auth config. Called synchronously from
7423
+ * `createAuthLifecycle()` for the same reason `configureDeletion` is: it must
7424
+ * take effect before any handler that reads `getDeviceAuthConfig()` can run.
7425
+ *
7426
+ * Both knobs are whole millisecond counts, and one that is not is refused here
7427
+ * rather than served. `intervalMs` is the reason the check exists: it leaves as
7428
+ * `intervalMillis` in the start and poll answers, which `DeviceAuthPollResponseSchema`
7429
+ * declares an integer and the mobile contract exports as one, so a fractional
7430
+ * value configured here would reach a generated client as a number its decoder
7431
+ * refuses — at the one moment the flow depends on that client asking again.
7432
+ */
7433
+ declare function configureDeviceAuth(options?: Partial<AuthDeviceAuthConfig>): void;
7434
+ /**
7435
+ * Read the current device-auth config. Safe to call any time — defaults apply
7436
+ * even if `createAuthLifecycle()` was never given a `deviceAuth` block.
7437
+ */
7438
+ declare function getDeviceAuthConfig(): AuthDeviceAuthConfig;
7439
+
7440
+ /**
7441
+ * @spfn/auth - Device code generation
7442
+ *
7443
+ * The two codes device-code login runs on, and the one-way function between the
7444
+ * device code and what is stored for it.
7445
+ *
7446
+ * They are different kinds of value and are treated differently everywhere. The
7447
+ * device code is a credential: the polling device holds it, nothing else proves
7448
+ * who that device is, so it is long, random, and stored only as a hash. The user
7449
+ * code is read off one screen and typed on another, so it is short and stored in
7450
+ * the clear — it authorizes nothing on its own, since only an already
7451
+ * authenticated caller can act on it.
7452
+ */
7453
+ /**
7454
+ * Alphabet the user code is drawn from.
7455
+ *
7456
+ * 0/O and 1/I/L are the pairs a person mistypes when copying a code between two
7457
+ * screens, so neither member of either pair is in the set. 31 characters over 8
7458
+ * positions is ~2^39 codes, which the per-IP and per-account rate limits on
7459
+ * every route that accepts one make unguessable in the ten minutes a code lives.
7460
+ */
7461
+ declare const USER_CODE_ALPHABET = "ABCDEFGHJKMNPQRSTUVWXYZ23456789";
7462
+ /** Characters in a user code, not counting the dash it is displayed with. */
7463
+ declare const USER_CODE_LENGTH = 8;
7464
+ /**
7465
+ * A fresh user code in stored form — uppercase, no dash.
7466
+ *
7467
+ * `randomInt` rather than `Math.random`: this is drawn from the same CSPRNG the
7468
+ * device code is, and a predictable user code lets an attacker have a victim
7469
+ * approve a code the attacker is polling.
7470
+ */
7471
+ declare function generateUserCode(): string;
7472
+ /** The stored form as a person reads it: `XXXX-XXXX`. */
7473
+ declare function formatUserCode(userCode: string): string;
7474
+ /**
7475
+ * Fold a typed user code back to the stored form.
7476
+ *
7477
+ * Someone reading `WXYZ-2345` off a screen types the dash, or spaces, or lower
7478
+ * case. All of those name the same code, so all of them have to reach the same
7479
+ * lookup — the alternative is a code that is on screen and still refused.
7480
+ *
7481
+ * Only the user code is normalized. The device code is a credential and is
7482
+ * matched byte for byte: accepting variant spellings of a credential is how one
7483
+ * token becomes several strings and a one-shot record is used twice.
7484
+ */
7485
+ declare function normalizeUserCode(input: string): string;
7486
+ /** A fresh device code, returned to the new device once and never stored. */
7487
+ declare function generateDeviceCode(): string;
7488
+ /**
7489
+ * What the row holds instead of the device code.
7490
+ *
7491
+ * Unsalted SHA-256, as with the ops-token and signup-link secrets: the input is
7492
+ * 256 bits of CSPRNG output, so there is no dictionary to defend against and a
7493
+ * per-row salt would only stop the exact-match lookup this has to support.
7494
+ */
7495
+ declare function hashDeviceCode(deviceCode: string): string;
7496
+
6901
7497
  /**
6902
7498
  * @spfn/auth - Centralized Logger
6903
7499
  *
@@ -6911,6 +7507,7 @@ declare const authLogger: {
6911
7507
  login: _spfn_core_logger.Logger;
6912
7508
  keyRotation: _spfn_core_logger.Logger;
6913
7509
  oauth: _spfn_core_logger.Logger;
7510
+ csrf: _spfn_core_logger.Logger;
6914
7511
  };
6915
7512
  session: _spfn_core_logger.Logger;
6916
7513
  service: _spfn_core_logger.Logger;
@@ -7103,6 +7700,38 @@ interface AuthLifecycleOptions extends AuthInitOptions {
7103
7700
  */
7104
7701
  onBeforePurge?: (user: AccountDeletionPurgeUser) => Promise<void>;
7105
7702
  };
7703
+ /**
7704
+ * Device-code login configuration
7705
+ *
7706
+ * Controls the codes handed out by `POST /_auth/device/start` and obeyed by
7707
+ * `POST /_auth/device/poll`. Both values are announced to the waiting device
7708
+ * in the start response, so they are resolved here rather than read per call,
7709
+ * and both must be a positive whole number of milliseconds — the interval is
7710
+ * published as an integer and a fraction is refused at startup rather than
7711
+ * handed to a client that cannot decode it.
7712
+ *
7713
+ * @example
7714
+ * ```typescript
7715
+ * createAuthLifecycle({
7716
+ * deviceAuth: {
7717
+ * ttlMs: 5 * 60 * 1000, // a code lives 5 minutes
7718
+ * intervalMs: 3000, // poll every 3 seconds
7719
+ * },
7720
+ * })
7721
+ * ```
7722
+ */
7723
+ deviceAuth?: {
7724
+ /**
7725
+ * How long a device code stays usable, in milliseconds.
7726
+ * @default 600000 (10 minutes)
7727
+ */
7728
+ ttlMs?: number;
7729
+ /**
7730
+ * Poll interval the server asks the waiting device to keep, in milliseconds.
7731
+ * @default 5000
7732
+ */
7733
+ intervalMs?: number;
7734
+ };
7106
7735
  }
7107
7736
  declare function createAuthLifecycle(options?: AuthLifecycleOptions): AuthLifecycleConfig;
7108
7737
 
@@ -7181,6 +7810,7 @@ declare const AuthProviderSchema: _sinclair_typebox.TUnion<[_sinclair_typebox.TL
7181
7810
  * 발행 시점:
7182
7811
  * - 이메일/전화 로그인 성공 시
7183
7812
  * - OAuth 기존 사용자 로그인 시
7813
+ * - 기기 코드 승인이 소비되어 새 기기 키가 등록될 때 (provider: 'device')
7184
7814
  *
7185
7815
  * @example
7186
7816
  * ```typescript
@@ -7193,7 +7823,7 @@ declare const authLoginEvent: _spfn_core_event.EventDef<{
7193
7823
  email?: string | undefined;
7194
7824
  phone?: string | undefined;
7195
7825
  userId: string;
7196
- provider: "email" | "phone" | "google" | "apple" | "github" | "kakao" | "naver" | "superself";
7826
+ provider: "email" | "phone" | "google" | "apple" | "github" | "kakao" | "naver" | "superself" | "device";
7197
7827
  }>;
7198
7828
  /**
7199
7829
  * auth.register - 회원가입 성공 이벤트
@@ -7350,4 +7980,4 @@ type AuthDeletionCancelledPayload = typeof authDeletionCancelledEvent._payload;
7350
7980
  type AuthDeletionCompletedPayload = typeof authDeletionCompletedEvent._payload;
7351
7981
  type OAuthUnlinkedPayload = typeof oauthUnlinkedEvent._payload;
7352
7982
 
7353
- export { type AccountDeletionPurgeUser, type AccountDeletionRequest, AccountDeletionRequestedBy, AccountDeletionRequestsRepository, type AuthConfig, AuthContext, type AuthDeletionCancelledPayload, type AuthDeletionCompletedPayload, type AuthDeletionConfig, type AuthDeletionRequestedPayload, type AuthLifecycleConfig, type AuthLifecycleOptions, type AuthLoginPayload, type AuthMetadataEntity, AuthMetadataRepository, AuthProviderSchema, type AuthRegisterPayload, type BeforeRegisterContext, COOKIE_NAMES, type CancelAccountDeletionParams, type CancelAccountDeletionResult, type CreateOAuthStateParams, DEFAULT_DELETION_ALLOW_SELF_IMMEDIATE, DEFAULT_DELETION_GRACE_PERIOD_DAYS, DEFAULT_DELETION_PURGE_CRON, DEFAULT_DELETION_PURGE_STRATEGY, DEFAULT_DELETION_SEND_NOTIFICATIONS, type DecryptedOAuthToken, type EmailNormalizationResult, EnvironmentKeyringTokenCipher, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, InvitationStatus, InvitationsRepository, type IssuedOpsToken, KeyAlgorithmType, KeysRepository, type NewAccountDeletionRequest, type NewAuthMetadataEntity, type NewInvitation, type NewOpsToken, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewSignupLinkToken, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, OAuthProvider, type OAuthState, type OAuthTokenCipher, type OAuthTokenContext, type OAuthTokenType, type OAuthUnlinkedPayload, type OpsToken, OpsTokensRepository, type PendingDeletionInfo, type Permission, type PermissionEntity, PermissionsRepository, PurgeStrategy, type PurgeUserResult, type RegisterChannel, type RequestAccountDeletionParams, type RequestAccountDeletionResult, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionPayload, type SignupLinkToken, SignupLinkTokensRepository, SocialAccountsRepository, SocialProvider, type SweepDuePurgesResult, type TokenPayload, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, type VerifiedOpsToken, type VerifyIdTokenParams, acceptInvitation, accountDeletionRequests, accountDeletionRequestsRepository, addPermissionToRole, appleProvider, assertCanAssignRole, authDeletionCancelledEvent, authDeletionCompletedEvent, authDeletionRequestedEvent, authJobRouter, authLogger, authLoginEvent, authMetadata, authMetadataRepository, authRegisterEvent, authSchema, cancelAccountDeletionService, cancelInvitation, checkUsernameAvailableService, configureAuth, configureDeletion, configureOAuthTokenCipher, createAuthDeletionJobRouter, createAuthDeletionPurgeJob, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, decryptToken, deleteInvitation, deleteRole, encryptToken, exchangeCodeForTokens, expireOldInvitations, generateOAuthNonce, generateToken, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getDeletionConfig, getDummyPasswordHash, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getLocale, getOneTimeTokenManager, getOpsToken, getOptionalAuth, getPendingDeletionInfo, getRole, getRoleByName, getRolePermissions, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, githubProvider, googleProvider, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashPassword, initOneTimeTokenManager, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, invitationsRepository, isEncrypted, isGoogleOAuthEnabled, issueOpsTokenService, kakaoProvider, keysRepository, listInvitations, listOpsTokensService, matchOAuthCsrfCookies, naverProvider, normalizeEmail, normalizeOptionalEmail, normalizeStoredEmails, oauthUnlinkedEvent, oneTimeTokenAuth, opsTokenAuth, opsTokens, opsTokensRepository, parseDuration, permissions, permissionsRepository, purgeUserService, refreshAccessToken, removePermissionFromRole, requestAccountDeletionService, requireAnyPermission, requireOpsScope, requirePermissions, requireRole, resendInvitation, revokeOpsTokenService, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, runBeforeRegister, setRolePermissions, signupLinkTokens, signupLinkTokensRepository, socialAccountsRepository, sweepDuePurges, updateLastLoginService, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyIdToken, verifyKeyFingerprint, verifyOAuthState, verifyOpsTokenService, verifyPassword, verifyToken };
7983
+ export { type AccountDeletionPurgeUser, type AccountDeletionRequest, AccountDeletionRequestedBy, AccountDeletionRequestsRepository, type AuthConfig, AuthContext, type AuthCsrfConfig, type AuthDeletionCancelledPayload, type AuthDeletionCompletedPayload, type AuthDeletionConfig, type AuthDeletionRequestedPayload, type AuthDeviceAuthConfig, type AuthLifecycleConfig, type AuthLifecycleOptions, type AuthLoginPayload, type AuthMetadataEntity, AuthMetadataRepository, AuthProviderSchema, type AuthRegisterPayload, type BeforeRegisterContext, COOKIE_NAMES, CSRF_HEADER, type CancelAccountDeletionParams, type CancelAccountDeletionResult, type CreateOAuthStateParams, type CsrfMode, DEFAULT_DELETION_ALLOW_SELF_IMMEDIATE, DEFAULT_DELETION_GRACE_PERIOD_DAYS, DEFAULT_DELETION_PURGE_CRON, DEFAULT_DELETION_PURGE_STRATEGY, DEFAULT_DELETION_SEND_NOTIFICATIONS, DEFAULT_DEVICE_AUTH_INTERVAL_MS, DEFAULT_DEVICE_AUTH_TTL_MS, DEVICE_AUTH_STATUSES, type DecryptedOAuthToken, type DeviceAuthStatus, type DeviceAuthorization, DeviceAuthorizationsRepository, type EmailNormalizationResult, EnvironmentKeyringTokenCipher, type GoogleTokenResponse, type GoogleUserInfo, type Invitation, type InvitationAcceptedPayload, type InvitationCreatedPayload, InvitationStatus, InvitationsRepository, type IssuedOpsToken, KeyAlgorithmType, KeysRepository, type NewAccountDeletionRequest, type NewAuthMetadataEntity, type NewDeviceAuthorization, type NewInvitation, type NewOpsToken, type NewPermission, type NewPermissionEntity, type NewRole, type NewRoleEntity, type NewRolePermission, type NewSignupLinkToken, type NewUser, type NewUserPermission, type NewUserProfile, type NewUserPublicKey, type NewUserSocialAccount, type NewVerificationCode, OAuthProvider, type OAuthState, type OAuthTokenCipher, type OAuthTokenContext, type OAuthTokenType, type OAuthUnlinkedPayload, type OpsToken, OpsTokensRepository, type PendingDeletionInfo, type Permission, type PermissionEntity, PermissionsRepository, PurgeStrategy, type PurgeUserResult, type RegisterChannel, type RequestAccountDeletionParams, type RequestAccountDeletionResult, type Role, type RoleEntity, type RoleGuardOptions, type RolePermission, RolePermissionsRepository, RolesRepository, type SessionPayload, type SignupLinkToken, SignupLinkTokensRepository, SocialAccountsRepository, SocialProvider, type SweepDuePurgesResult, type TokenPayload, USER_CODE_ALPHABET, USER_CODE_LENGTH, type UpdateProfileParams, type User, type UserPermission, UserPermissionsRepository, type UserProfile, UserProfilesRepository, type UserPublicKey, type UserSocialAccount, UsersRepository, type VerificationCode, VerificationCodesRepository, VerificationPurpose, type VerifiedOpsToken, type VerifyIdTokenParams, acceptInvitation, accountDeletionRequests, accountDeletionRequestsRepository, addPermissionToRole, appleProvider, assertCanAssignRole, authDeletionCancelledEvent, authDeletionCompletedEvent, authDeletionRequestedEvent, authJobRouter, authLogger, authLoginEvent, authMetadata, authMetadataRepository, authRegisterEvent, authSchema, cancelAccountDeletionService, cancelInvitation, checkUsernameAvailableService, configureAuth, configureDeletion, configureDeviceAuth, configureOAuthTokenCipher, createAuthDeletionJobRouter, createAuthDeletionPurgeJob, createAuthLifecycle, createInvitation, createOAuthState, createRole, decodeToken, decryptToken, deleteInvitation, deleteRole, deriveCsrfToken, deviceAuthorizations, deviceAuthorizationsRepository, encryptToken, exchangeCodeForTokens, expireOldInvitations, formatUserCode, generateDeviceCode, generateOAuthNonce, generateToken, generateUserCode, getAllRoles, getAuth, getAuthConfig, getAuthSessionService, getCsrfExemptPaths, getCsrfMode, getDeletionConfig, getDeviceAuthConfig, getDummyPasswordHash, getGoogleAuthUrl, getGoogleOAuthConfig, getGoogleUserInfo, getInvitationByToken, getInvitationWithDetails, getKeyId, getLocale, getOneTimeTokenManager, getOpsToken, getOptionalAuth, getPendingDeletionInfo, getRole, getRoleByName, getRolePermissions, getSessionTtl, getUser, getUserByEmailService, getUserByIdService, getUserByPhoneService, getUserId, getUserPermissions, getUserProfileService, getUserRole, githubProvider, googleProvider, hasAllPermissions, hasAnyPermission, hasAnyRole, hasPermission, hasRole, hashDeviceCode, hashPassword, initOneTimeTokenManager, initializeAuth, invitationAcceptedEvent, invitationCreatedEvent, invitationsRepository, isEncrypted, isGoogleOAuthEnabled, issueOpsTokenService, kakaoProvider, keysRepository, listInvitations, listOpsTokensService, matchOAuthCsrfCookies, matchesCsrfToken, naverProvider, normalizeEmail, normalizeOptionalEmail, normalizeStoredEmails, normalizeUserCode, oauthUnlinkedEvent, oneTimeTokenAuth, opsTokenAuth, opsTokens, opsTokensRepository, parseDuration, permissions, permissionsRepository, purgeUserService, refreshAccessToken, removePermissionFromRole, requestAccountDeletionService, requireAnyPermission, requireOpsScope, requirePermissions, requireRole, resendInvitation, revokeOpsTokenService, roleGuard, rolePermissions, rolePermissionsRepository, roles, rolesRepository, runBeforeRegister, setRolePermissions, signupLinkTokens, signupLinkTokensRepository, socialAccountsRepository, sweepDuePurges, updateLastLoginService, updateLocaleService, updateRole, updateUserProfileService, updateUserService, updateUsernameService, userInvitations, userPermissions, userPermissionsRepository, userProfiles, userProfilesRepository, userPublicKeys, userSocialAccounts, users, usersRepository, validateInvitation, validatePasswordStrength, verificationCodes, verificationCodesRepository, verifyClientToken, verifyIdToken, verifyKeyFingerprint, verifyOAuthState, verifyOpsTokenService, verifyPassword, verifyToken };