@spfn/auth 0.3.0-beta.1 → 0.3.0-beta.2

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.js CHANGED
@@ -5432,6 +5432,38 @@ var init_auth_metadata = __esm({
5432
5432
  }
5433
5433
  });
5434
5434
 
5435
+ // src/server/entities/ops-tokens.ts
5436
+ import { text as text12 } from "drizzle-orm/pg-core";
5437
+ import { id as id12, timestamps as timestamps11, utcTimestamp as utcTimestamp8 } from "@spfn/core/db";
5438
+ var opsTokens;
5439
+ var init_ops_tokens = __esm({
5440
+ "src/server/entities/ops-tokens.ts"() {
5441
+ "use strict";
5442
+ init_schema4();
5443
+ opsTokens = authSchema.table(
5444
+ "ops_tokens",
5445
+ {
5446
+ id: id12(),
5447
+ // Operator-facing label ("ci-deploy", "rayim-laptop")
5448
+ name: text12("name").notNull(),
5449
+ // SHA-256 hex of the token secret. Lookup key — the secret never lands
5450
+ // here, and the unique constraint doubles as the lookup index.
5451
+ tokenHash: text12("token_hash").notNull().unique(),
5452
+ // Granted scopes as permission strings ('waitlist:read', ...).
5453
+ // '*' grants every scope.
5454
+ scopes: text12("scopes").array().notNull(),
5455
+ // null = the token does not expire
5456
+ expiresAt: utcTimestamp8("expires_at"),
5457
+ // null = active; a timestamp revokes the token permanently
5458
+ revokedAt: utcTimestamp8("revoked_at"),
5459
+ // Last successful verification, updated fire-and-forget
5460
+ lastUsedAt: utcTimestamp8("last_used_at"),
5461
+ ...timestamps11()
5462
+ }
5463
+ );
5464
+ }
5465
+ });
5466
+
5435
5467
  // src/server/entities/index.ts
5436
5468
  var init_entities = __esm({
5437
5469
  "src/server/entities/index.ts"() {
@@ -5449,6 +5481,7 @@ var init_entities = __esm({
5449
5481
  init_role_permissions();
5450
5482
  init_user_permissions();
5451
5483
  init_auth_metadata();
5484
+ init_ops_tokens();
5452
5485
  }
5453
5486
  });
5454
5487
 
@@ -5466,8 +5499,8 @@ var init_users_repository = __esm({
5466
5499
  * ID로 사용자 조회
5467
5500
  * Read replica 사용
5468
5501
  */
5469
- async findById(id12) {
5470
- const result = await this.readDb.select().from(users).where(eq(users.id, id12)).limit(1);
5502
+ async findById(id13) {
5503
+ const result = await this.readDb.select().from(users).where(eq(users.id, id13)).limit(1);
5471
5504
  return result[0] ?? null;
5472
5505
  }
5473
5506
  /**
@@ -5477,8 +5510,8 @@ var init_users_repository = __esm({
5477
5510
  * 안 되는 게이트(OAuth 세션 발급 등)가 사용한다. 일반 조회는 `findById`(replica)를
5478
5511
  * 계속 사용할 것.
5479
5512
  */
5480
- async findByIdOnPrimary(id12) {
5481
- const result = await this.db.select().from(users).where(eq(users.id, id12)).limit(1);
5513
+ async findByIdOnPrimary(id13) {
5514
+ const result = await this.db.select().from(users).where(eq(users.id, id13)).limit(1);
5482
5515
  return result[0] ?? null;
5483
5516
  }
5484
5517
  /**
@@ -5531,13 +5564,13 @@ var init_users_repository = __esm({
5531
5564
  *
5532
5565
  * roleId가 null인 유저는 role: null 반환
5533
5566
  */
5534
- async findByIdWithRole(id12) {
5567
+ async findByIdWithRole(id13) {
5535
5568
  const result = await this.readDb.select({
5536
5569
  user: users,
5537
5570
  roleName: roles.name,
5538
5571
  roleDisplayName: roles.displayName,
5539
5572
  rolePriority: roles.priority
5540
- }).from(users).leftJoin(roles, eq(users.roleId, roles.id)).where(eq(users.id, id12)).limit(1);
5573
+ }).from(users).leftJoin(roles, eq(users.roleId, roles.id)).where(eq(users.id, id13)).limit(1);
5541
5574
  const row = result[0];
5542
5575
  if (!row) {
5543
5576
  return null;
@@ -5558,8 +5591,8 @@ var init_users_repository = __esm({
5558
5591
  * 사용자 정보 업데이트
5559
5592
  * Write primary 사용
5560
5593
  */
5561
- async updateById(id12, data) {
5562
- const result = await this.db.update(users).set(data).where(eq(users.id, id12)).returning();
5594
+ async updateById(id13, data) {
5595
+ const result = await this.db.update(users).set(data).where(eq(users.id, id13)).returning();
5563
5596
  return result[0] ?? null;
5564
5597
  }
5565
5598
  /**
@@ -5571,10 +5604,10 @@ var init_users_repository = __esm({
5571
5604
  * status가 바뀐 상태) 시 null을 반환하며 예외를 던지지 않는다.
5572
5605
  * Write primary 사용
5573
5606
  */
5574
- async reactivateFromPendingDeletion(id12) {
5607
+ async reactivateFromPendingDeletion(id13) {
5575
5608
  const result = await this.db.update(users).set({ status: "active" }).where(
5576
5609
  and(
5577
- eq(users.id, id12),
5610
+ eq(users.id, id13),
5578
5611
  eq(users.status, "pending_deletion")
5579
5612
  )
5580
5613
  ).returning();
@@ -5584,32 +5617,32 @@ var init_users_repository = __esm({
5584
5617
  * 비밀번호 업데이트
5585
5618
  * Write primary 사용
5586
5619
  */
5587
- async updatePassword(id12, passwordHash, clearPasswordChangeRequired = true) {
5620
+ async updatePassword(id13, passwordHash, clearPasswordChangeRequired = true) {
5588
5621
  const updateData = {
5589
5622
  passwordHash
5590
5623
  };
5591
5624
  if (clearPasswordChangeRequired) {
5592
5625
  updateData.passwordChangeRequired = false;
5593
5626
  }
5594
- const result = await this.db.update(users).set(updateData).where(eq(users.id, id12)).returning();
5627
+ const result = await this.db.update(users).set(updateData).where(eq(users.id, id13)).returning();
5595
5628
  return result[0] ?? null;
5596
5629
  }
5597
5630
  /**
5598
5631
  * 마지막 로그인 시간 업데이트
5599
5632
  * Write primary 사용
5600
5633
  */
5601
- async updateLastLogin(id12) {
5634
+ async updateLastLogin(id13) {
5602
5635
  const result = await this.db.update(users).set({
5603
5636
  lastLoginAt: /* @__PURE__ */ new Date()
5604
- }).where(eq(users.id, id12)).returning();
5637
+ }).where(eq(users.id, id13)).returning();
5605
5638
  return result[0] ?? null;
5606
5639
  }
5607
5640
  /**
5608
5641
  * 사용자 삭제
5609
5642
  * Write primary 사용
5610
5643
  */
5611
- async deleteById(id12) {
5612
- const result = await this.db.delete(users).where(eq(users.id, id12)).returning();
5644
+ async deleteById(id13) {
5645
+ const result = await this.db.delete(users).where(eq(users.id, id13)).returning();
5613
5646
  return result[0] ?? null;
5614
5647
  }
5615
5648
  /**
@@ -5957,14 +5990,14 @@ var init_keys_repository = __esm({
5957
5990
  * stored, so it answers "since when has this device been on this release"
5958
5991
  * rather than "when was it last seen", which lastUsedAt already answers.
5959
5992
  */
5960
- async updateLastUsedById(id12, identity) {
5993
+ async updateLastUsedById(id13, identity) {
5961
5994
  const staleBefore = new Date(Date.now() - LAST_USED_THROTTLE_MS);
5962
5995
  const lastUsedIsStale = or(
5963
5996
  isNull(userPublicKeys.lastUsedAt),
5964
5997
  lt(userPublicKeys.lastUsedAt, staleBefore)
5965
5998
  );
5966
5999
  if (!identity) {
5967
- await this.db.update(userPublicKeys).set({ lastUsedAt: /* @__PURE__ */ new Date() }).where(and2(eq2(userPublicKeys.id, id12), lastUsedIsStale));
6000
+ await this.db.update(userPublicKeys).set({ lastUsedAt: /* @__PURE__ */ new Date() }).where(and2(eq2(userPublicKeys.id, id13), lastUsedIsStale));
5968
6001
  return;
5969
6002
  }
5970
6003
  const identityChanged = sql4`(
@@ -5981,7 +6014,7 @@ var init_keys_repository = __esm({
5981
6014
  clientContractVersion: identity.contractVersion,
5982
6015
  clientSeenAt: sql4`CASE WHEN ${identityChanged} THEN ${nowParam} ELSE ${userPublicKeys.clientSeenAt} END`
5983
6016
  }).where(and2(
5984
- eq2(userPublicKeys.id, id12),
6017
+ eq2(userPublicKeys.id, id13),
5985
6018
  or(lastUsedIsStale, identityChanged)
5986
6019
  ));
5987
6020
  }
@@ -6020,8 +6053,8 @@ var init_verification_codes_repository = __esm({
6020
6053
  * ID로 인증 코드 조회
6021
6054
  * Read replica 사용
6022
6055
  */
6023
- async findById(id12) {
6024
- const result = await this.readDb.select().from(verificationCodes).where(eq3(verificationCodes.id, id12)).limit(1);
6056
+ async findById(id13) {
6057
+ const result = await this.readDb.select().from(verificationCodes).where(eq3(verificationCodes.id, id13)).limit(1);
6025
6058
  return result[0] ?? null;
6026
6059
  }
6027
6060
  /**
@@ -6035,22 +6068,22 @@ var init_verification_codes_repository = __esm({
6035
6068
  * 인증 코드 사용 처리
6036
6069
  * Write primary 사용
6037
6070
  */
6038
- async markAsUsed(id12) {
6071
+ async markAsUsed(id13) {
6039
6072
  const result = await this.db.update(verificationCodes).set({
6040
6073
  usedAt: /* @__PURE__ */ new Date()
6041
- }).where(eq3(verificationCodes.id, id12)).returning();
6074
+ }).where(eq3(verificationCodes.id, id13)).returning();
6042
6075
  return result[0] ?? null;
6043
6076
  }
6044
6077
  /**
6045
6078
  * 시도 횟수 증가
6046
6079
  * Write primary 사용
6047
6080
  */
6048
- async incrementAttempts(id12) {
6049
- const code = await this.findById(id12);
6081
+ async incrementAttempts(id13) {
6082
+ const code = await this.findById(id13);
6050
6083
  if (!code) return null;
6051
6084
  const result = await this.db.update(verificationCodes).set({
6052
6085
  attempts: code.attempts + 1
6053
- }).where(eq3(verificationCodes.id, id12)).returning();
6086
+ }).where(eq3(verificationCodes.id, id13)).returning();
6054
6087
  return result[0] ?? null;
6055
6088
  }
6056
6089
  /**
@@ -6106,8 +6139,8 @@ var init_roles_repository = __esm({
6106
6139
  /**
6107
6140
  * ID로 역할 조회
6108
6141
  */
6109
- async findById(id12) {
6110
- const result = await this.readDb.select().from(roles).where(eq4(roles.id, id12)).limit(1);
6142
+ async findById(id13) {
6143
+ const result = await this.readDb.select().from(roles).where(eq4(roles.id, id13)).limit(1);
6111
6144
  return result[0] ?? null;
6112
6145
  }
6113
6146
  /**
@@ -6138,15 +6171,15 @@ var init_roles_repository = __esm({
6138
6171
  /**
6139
6172
  * 역할 업데이트
6140
6173
  */
6141
- async updateById(id12, data) {
6142
- const result = await this.db.update(roles).set(data).where(eq4(roles.id, id12)).returning();
6174
+ async updateById(id13, data) {
6175
+ const result = await this.db.update(roles).set(data).where(eq4(roles.id, id13)).returning();
6143
6176
  return result[0] ?? null;
6144
6177
  }
6145
6178
  /**
6146
6179
  * 역할 삭제
6147
6180
  */
6148
- async deleteById(id12) {
6149
- const result = await this.db.delete(roles).where(eq4(roles.id, id12)).returning();
6181
+ async deleteById(id13) {
6182
+ const result = await this.db.delete(roles).where(eq4(roles.id, id13)).returning();
6150
6183
  return result[0] ?? null;
6151
6184
  }
6152
6185
  };
@@ -6166,8 +6199,8 @@ var init_permissions_repository = __esm({
6166
6199
  /**
6167
6200
  * ID로 권한 조회
6168
6201
  */
6169
- async findById(id12) {
6170
- const result = await this.readDb.select().from(permissions).where(eq5(permissions.id, id12)).limit(1);
6202
+ async findById(id13) {
6203
+ const result = await this.readDb.select().from(permissions).where(eq5(permissions.id, id13)).limit(1);
6171
6204
  return result[0] ?? null;
6172
6205
  }
6173
6206
  /**
@@ -6218,15 +6251,15 @@ var init_permissions_repository = __esm({
6218
6251
  /**
6219
6252
  * 권한 업데이트
6220
6253
  */
6221
- async updateById(id12, data) {
6222
- const result = await this.db.update(permissions).set(data).where(eq5(permissions.id, id12)).returning();
6254
+ async updateById(id13, data) {
6255
+ const result = await this.db.update(permissions).set(data).where(eq5(permissions.id, id13)).returning();
6223
6256
  return result[0] ?? null;
6224
6257
  }
6225
6258
  /**
6226
6259
  * 권한 삭제
6227
6260
  */
6228
- async deleteById(id12) {
6229
- const result = await this.db.delete(permissions).where(eq5(permissions.id, id12)).returning();
6261
+ async deleteById(id13) {
6262
+ const result = await this.db.delete(permissions).where(eq5(permissions.id, id13)).returning();
6230
6263
  return result[0] ?? null;
6231
6264
  }
6232
6265
  };
@@ -6356,8 +6389,8 @@ var init_user_permissions_repository = __esm({
6356
6389
  /**
6357
6390
  * 사용자 권한 오버라이드 업데이트
6358
6391
  */
6359
- async updateById(id12, data) {
6360
- const result = await this.db.update(userPermissions).set(data).where(eq7(userPermissions.id, id12)).returning();
6392
+ async updateById(id13, data) {
6393
+ const result = await this.db.update(userPermissions).set(data).where(eq7(userPermissions.id, id13)).returning();
6361
6394
  return result[0] ?? null;
6362
6395
  }
6363
6396
  /**
@@ -6409,8 +6442,8 @@ var init_user_profiles_repository = __esm({
6409
6442
  /**
6410
6443
  * ID로 프로필 조회
6411
6444
  */
6412
- async findById(id12) {
6413
- const result = await this.readDb.select().from(userProfiles).where(eq8(userProfiles.id, id12)).limit(1);
6445
+ async findById(id13) {
6446
+ const result = await this.readDb.select().from(userProfiles).where(eq8(userProfiles.id, id13)).limit(1);
6414
6447
  return result[0] ?? null;
6415
6448
  }
6416
6449
  /**
@@ -6436,8 +6469,8 @@ var init_user_profiles_repository = __esm({
6436
6469
  /**
6437
6470
  * 프로필 업데이트 (by ID)
6438
6471
  */
6439
- async updateById(id12, data) {
6440
- const result = await this.db.update(userProfiles).set(data).where(eq8(userProfiles.id, id12)).returning();
6472
+ async updateById(id13, data) {
6473
+ const result = await this.db.update(userProfiles).set(data).where(eq8(userProfiles.id, id13)).returning();
6441
6474
  return result[0] ?? null;
6442
6475
  }
6443
6476
  /**
@@ -6450,8 +6483,8 @@ var init_user_profiles_repository = __esm({
6450
6483
  /**
6451
6484
  * 프로필 삭제 (by ID)
6452
6485
  */
6453
- async deleteById(id12) {
6454
- const result = await this.db.delete(userProfiles).where(eq8(userProfiles.id, id12)).returning();
6486
+ async deleteById(id13) {
6487
+ const result = await this.db.delete(userProfiles).where(eq8(userProfiles.id, id13)).returning();
6455
6488
  return result[0] ?? null;
6456
6489
  }
6457
6490
  /**
@@ -6541,8 +6574,8 @@ var init_invitations_repository = __esm({
6541
6574
  /**
6542
6575
  * ID로 초대 조회
6543
6576
  */
6544
- async findById(id12) {
6545
- const result = await this.readDb.select().from(userInvitations).where(eq9(userInvitations.id, id12)).limit(1);
6577
+ async findById(id13) {
6578
+ const result = await this.readDb.select().from(userInvitations).where(eq9(userInvitations.id, id13)).limit(1);
6546
6579
  return result[0] ?? null;
6547
6580
  }
6548
6581
  /**
@@ -6585,7 +6618,7 @@ var init_invitations_repository = __esm({
6585
6618
  /**
6586
6619
  * 초대 상태 업데이트
6587
6620
  */
6588
- async updateStatus(id12, status, timestamp2) {
6621
+ async updateStatus(id13, status, timestamp2) {
6589
6622
  const updates = {
6590
6623
  status
6591
6624
  };
@@ -6596,14 +6629,14 @@ var init_invitations_repository = __esm({
6596
6629
  updates.cancelledAt = timestamp2;
6597
6630
  }
6598
6631
  }
6599
- const result = await this.db.update(userInvitations).set(updates).where(eq9(userInvitations.id, id12)).returning();
6632
+ const result = await this.db.update(userInvitations).set(updates).where(eq9(userInvitations.id, id13)).returning();
6600
6633
  return result[0] ?? null;
6601
6634
  }
6602
6635
  /**
6603
6636
  * 초대 삭제
6604
6637
  */
6605
- async deleteById(id12) {
6606
- const result = await this.db.delete(userInvitations).where(eq9(userInvitations.id, id12)).returning();
6638
+ async deleteById(id13) {
6639
+ const result = await this.db.delete(userInvitations).where(eq9(userInvitations.id, id13)).returning();
6607
6640
  return result[0] ?? null;
6608
6641
  }
6609
6642
  /**
@@ -6698,30 +6731,30 @@ var init_invitations_repository = __esm({
6698
6731
  /**
6699
6732
  * 초대 업데이트 (일반 업데이트 - 모든 필드 가능)
6700
6733
  */
6701
- async updateById(id12, data) {
6702
- const result = await this.db.update(userInvitations).set(data).where(eq9(userInvitations.id, id12)).returning();
6734
+ async updateById(id13, data) {
6735
+ const result = await this.db.update(userInvitations).set(data).where(eq9(userInvitations.id, id13)).returning();
6703
6736
  return result[0] ?? null;
6704
6737
  }
6705
6738
  /**
6706
6739
  * 초대 재전송 (status와 expiresAt 동시 업데이트)
6707
6740
  */
6708
- async resend(id12, newExpiresAt) {
6741
+ async resend(id13, newExpiresAt) {
6709
6742
  const result = await this.db.update(userInvitations).set({
6710
6743
  status: "pending",
6711
6744
  expiresAt: newExpiresAt
6712
- }).where(eq9(userInvitations.id, id12)).returning();
6745
+ }).where(eq9(userInvitations.id, id13)).returning();
6713
6746
  return result[0] ?? null;
6714
6747
  }
6715
6748
  /**
6716
6749
  * 초대 취소 (status, metadata 동시 업데이트)
6717
6750
  */
6718
- async cancel(id12, cancelledBy, reason, currentMetadata) {
6751
+ async cancel(id13, cancelledBy, reason, currentMetadata) {
6719
6752
  const newMetadata = currentMetadata ? { ...currentMetadata, cancelReason: reason, cancelledBy } : { cancelReason: reason, cancelledBy };
6720
6753
  const result = await this.db.update(userInvitations).set({
6721
6754
  status: "cancelled",
6722
6755
  cancelledAt: /* @__PURE__ */ new Date(),
6723
6756
  metadata: newMetadata
6724
- }).where(eq9(userInvitations.id, id12)).returning();
6757
+ }).where(eq9(userInvitations.id, id13)).returning();
6725
6758
  return result[0] ?? null;
6726
6759
  }
6727
6760
  };
@@ -7446,11 +7479,11 @@ var init_social_accounts_repository = __esm({
7446
7479
  * 토큰 정보 업데이트
7447
7480
  * Write primary 사용
7448
7481
  */
7449
- async updateTokens(id12, data) {
7482
+ async updateTokens(id13, data) {
7450
7483
  const accounts = await this.db.select({
7451
7484
  provider: userSocialAccounts.provider,
7452
7485
  providerUserId: userSocialAccounts.providerUserId
7453
- }).from(userSocialAccounts).where(eq10(userSocialAccounts.id, id12)).limit(1);
7486
+ }).from(userSocialAccounts).where(eq10(userSocialAccounts.id, id13)).limit(1);
7454
7487
  const account = accounts[0];
7455
7488
  if (!account) {
7456
7489
  return null;
@@ -7464,15 +7497,15 @@ var init_social_accounts_repository = __esm({
7464
7497
  ...data,
7465
7498
  accessToken: data.accessToken ? await encryptToken(data.accessToken, context("access")) : data.accessToken,
7466
7499
  refreshToken: data.refreshToken ? await encryptToken(data.refreshToken, context("refresh")) : data.refreshToken
7467
- }).where(eq10(userSocialAccounts.id, id12)).returning();
7500
+ }).where(eq10(userSocialAccounts.id, id13)).returning();
7468
7501
  return this.decryptAccount(result[0] ?? null);
7469
7502
  }
7470
7503
  /**
7471
7504
  * 소셜 계정 삭제
7472
7505
  * Write primary 사용
7473
7506
  */
7474
- async deleteById(id12) {
7475
- const result = await this.db.delete(userSocialAccounts).where(eq10(userSocialAccounts.id, id12)).returning();
7507
+ async deleteById(id13) {
7508
+ const result = await this.db.delete(userSocialAccounts).where(eq10(userSocialAccounts.id, id13)).returning();
7476
7509
  return result[0] ?? null;
7477
7510
  }
7478
7511
  /**
@@ -7552,8 +7585,8 @@ var init_account_deletion_requests_repository = __esm({
7552
7585
  * ID로 요청 조회
7553
7586
  * Read replica 사용
7554
7587
  */
7555
- async findById(id12) {
7556
- const result = await this.readDb.select().from(accountDeletionRequests).where(eq12(accountDeletionRequests.id, id12)).limit(1);
7588
+ async findById(id13) {
7589
+ const result = await this.readDb.select().from(accountDeletionRequests).where(eq12(accountDeletionRequests.id, id13)).limit(1);
7557
7590
  return result[0] ?? null;
7558
7591
  }
7559
7592
  /**
@@ -7612,13 +7645,13 @@ var init_account_deletion_requests_repository = __esm({
7612
7645
  * cancelled) 시 null을 반환하니 호출자가 그 결과를 확인해야 한다.
7613
7646
  * Write primary 사용
7614
7647
  */
7615
- async markCancelled(id12) {
7648
+ async markCancelled(id13) {
7616
7649
  const result = await this.db.update(accountDeletionRequests).set({
7617
7650
  status: "cancelled",
7618
7651
  cancelledAt: /* @__PURE__ */ new Date()
7619
7652
  }).where(
7620
7653
  and8(
7621
- eq12(accountDeletionRequests.id, id12),
7654
+ eq12(accountDeletionRequests.id, id13),
7622
7655
  eq12(accountDeletionRequests.status, "pending")
7623
7656
  )
7624
7657
  ).returning();
@@ -7634,14 +7667,14 @@ var init_account_deletion_requests_repository = __esm({
7634
7667
  * destructive DML을 실행하기 **전에** 반드시 이 결과를 확인해야 한다.
7635
7668
  * Write primary 사용
7636
7669
  */
7637
- async markCompleted(id12, purgeStrategy) {
7670
+ async markCompleted(id13, purgeStrategy) {
7638
7671
  const result = await this.db.update(accountDeletionRequests).set({
7639
7672
  status: "completed",
7640
7673
  completedAt: /* @__PURE__ */ new Date(),
7641
7674
  purgeStrategy
7642
7675
  }).where(
7643
7676
  and8(
7644
- eq12(accountDeletionRequests.id, id12),
7677
+ eq12(accountDeletionRequests.id, id13),
7645
7678
  eq12(accountDeletionRequests.status, "pending")
7646
7679
  )
7647
7680
  ).returning();
@@ -7652,6 +7685,52 @@ var init_account_deletion_requests_repository = __esm({
7652
7685
  }
7653
7686
  });
7654
7687
 
7688
+ // src/server/repositories/ops-tokens.repository.ts
7689
+ import { and as and9, desc as desc3, eq as eq13, isNull as isNull4 } from "drizzle-orm";
7690
+ import { BaseRepository as BaseRepository13 } from "@spfn/core/db";
7691
+ var OpsTokensRepository, opsTokensRepository;
7692
+ var init_ops_tokens_repository = __esm({
7693
+ "src/server/repositories/ops-tokens.repository.ts"() {
7694
+ "use strict";
7695
+ init_ops_tokens();
7696
+ OpsTokensRepository = class extends BaseRepository13 {
7697
+ /**
7698
+ * Lookup by the secret's hash — the verification path.
7699
+ *
7700
+ * Reads the primary, not the replica, unlike every other SELECT here.
7701
+ * Revocation writes to the primary, so a replica read would keep
7702
+ * authenticating a revoked token for the length of the replication lag —
7703
+ * and revocation is documented as taking effect immediately.
7704
+ */
7705
+ async findByTokenHash(tokenHash) {
7706
+ const result = await this.db.select().from(opsTokens).where(eq13(opsTokens.tokenHash, tokenHash)).limit(1);
7707
+ return result[0] ?? null;
7708
+ }
7709
+ async create(data) {
7710
+ const result = await this.db.insert(opsTokens).values(data).returning();
7711
+ return result[0];
7712
+ }
7713
+ async list() {
7714
+ return await this.readDb.select().from(opsTokens).orderBy(desc3(opsTokens.createdAt));
7715
+ }
7716
+ /**
7717
+ * Revoke an active token. Returns null when the id does not exist or the
7718
+ * token is already revoked — the first revocation's timestamp is never
7719
+ * overwritten.
7720
+ */
7721
+ async revokeById(id13) {
7722
+ const result = await this.db.update(opsTokens).set({ revokedAt: /* @__PURE__ */ new Date() }).where(and9(eq13(opsTokens.id, id13), isNull4(opsTokens.revokedAt))).returning();
7723
+ return result[0] ?? null;
7724
+ }
7725
+ /** Fire-and-forget from the verification path. */
7726
+ async updateLastUsedById(id13) {
7727
+ await this.db.update(opsTokens).set({ lastUsedAt: /* @__PURE__ */ new Date() }).where(eq13(opsTokens.id, id13));
7728
+ }
7729
+ };
7730
+ opsTokensRepository = new OpsTokensRepository();
7731
+ }
7732
+ });
7733
+
7655
7734
  // src/server/repositories/index.ts
7656
7735
  var init_repositories = __esm({
7657
7736
  "src/server/repositories/index.ts"() {
@@ -7668,6 +7747,7 @@ var init_repositories = __esm({
7668
7747
  init_social_accounts_repository();
7669
7748
  init_auth_metadata_repository();
7670
7749
  init_account_deletion_requests_repository();
7750
+ init_ops_tokens_repository();
7671
7751
  }
7672
7752
  });
7673
7753
 
@@ -7759,7 +7839,7 @@ async function removePermissionFromRole(roleId, permissionId) {
7759
7839
  }
7760
7840
  async function setRolePermissions(roleId, permissionIds) {
7761
7841
  const roleIdNum = Number(roleId);
7762
- const permissionIdNums = permissionIds.map((id12) => Number(id12));
7842
+ const permissionIdNums = permissionIds.map((id13) => Number(id13));
7763
7843
  await rolePermissionsRepository.setPermissionsForRole(roleIdNum, permissionIdNums);
7764
7844
  }
7765
7845
  async function getAllRoles(includeInactive = false) {
@@ -7779,7 +7859,7 @@ async function getRolePermissions(roleId) {
7779
7859
  }
7780
7860
  const permissionIds = mappings.map((m) => m.permissionId);
7781
7861
  const perms = await Promise.all(
7782
- permissionIds.map((id12) => permissionsRepository.findById(id12))
7862
+ permissionIds.map((id13) => permissionsRepository.findById(id13))
7783
7863
  );
7784
7864
  return perms.filter((p) => p !== null).map((p) => p.name);
7785
7865
  }
@@ -8595,8 +8675,8 @@ async function verifyReauthCredential(user, params) {
8595
8675
  throw new VerificationTokenTargetMismatchError();
8596
8676
  }
8597
8677
  }
8598
- async function sendDeletionEmail(to, subject, text12) {
8599
- const result = await sendEmail2({ to, subject, text: text12 });
8678
+ async function sendDeletionEmail(to, subject, text13) {
8679
+ const result = await sendEmail2({ to, subject, text: text13 });
8600
8680
  if (!result.success) {
8601
8681
  authLogger.email.error("Failed to send account deletion email", { to, subject, error: result.error });
8602
8682
  }
@@ -9144,7 +9224,7 @@ async function getUserPermissions(userId) {
9144
9224
  const permIds = rolePermMappings.map((rp) => rp.permissionId);
9145
9225
  if (permIds.length > 0) {
9146
9226
  const rolePerms = await Promise.all(
9147
- permIds.map((id12) => permissionsRepository.findById(id12))
9227
+ permIds.map((id13) => permissionsRepository.findById(id13))
9148
9228
  );
9149
9229
  for (const perm of rolePerms) {
9150
9230
  if (perm && perm.isActive) {
@@ -9357,20 +9437,20 @@ async function acceptInvitation(params) {
9357
9437
  async function listInvitations(params) {
9358
9438
  return await invitationsRepository.list(params);
9359
9439
  }
9360
- async function cancelInvitation(id12, cancelledBy, reason) {
9361
- const invitation = await invitationsRepository.findById(id12);
9440
+ async function cancelInvitation(id13, cancelledBy, reason) {
9441
+ const invitation = await invitationsRepository.findById(id13);
9362
9442
  if (!invitation) {
9363
9443
  throw new NotFoundError3({ message: "Invitation not found", resource: "Invitation" });
9364
9444
  }
9365
9445
  if (invitation.status !== "pending") {
9366
9446
  throw new ConflictError({ message: `Cannot cancel ${invitation.status} invitation` });
9367
9447
  }
9368
- await invitationsRepository.cancel(id12, cancelledBy, reason, invitation.metadata);
9448
+ await invitationsRepository.cancel(id13, cancelledBy, reason, invitation.metadata);
9369
9449
  console.log(`[Auth] \u26A0\uFE0F Invitation cancelled: ${invitation.email} (reason: ${reason || "none"})`);
9370
9450
  }
9371
- async function deleteInvitation(id12) {
9372
- await invitationsRepository.deleteById(id12);
9373
- console.log(`[Auth] \u{1F5D1}\uFE0F Invitation deleted: ${id12}`);
9451
+ async function deleteInvitation(id13) {
9452
+ await invitationsRepository.deleteById(id13);
9453
+ console.log(`[Auth] \u{1F5D1}\uFE0F Invitation deleted: ${id13}`);
9374
9454
  }
9375
9455
  async function expireOldInvitations() {
9376
9456
  const count = await invitationsRepository.updateExpiredInvitations();
@@ -9379,8 +9459,8 @@ async function expireOldInvitations() {
9379
9459
  }
9380
9460
  return count;
9381
9461
  }
9382
- async function resendInvitation(id12, expiresInDays = 7) {
9383
- const invitation = await invitationsRepository.findById(id12);
9462
+ async function resendInvitation(id13, expiresInDays = 7) {
9463
+ const invitation = await invitationsRepository.findById(id13);
9384
9464
  if (!invitation) {
9385
9465
  throw new NotFoundError3({ message: "Invitation not found", resource: "Invitation" });
9386
9466
  }
@@ -9388,7 +9468,7 @@ async function resendInvitation(id12, expiresInDays = 7) {
9388
9468
  throw new ConflictError({ message: `Cannot resend ${invitation.status} invitation` });
9389
9469
  }
9390
9470
  const newExpiresAt = calculateExpiresAt(expiresInDays);
9391
- const updated = await invitationsRepository.resend(id12, newExpiresAt);
9471
+ const updated = await invitationsRepository.resend(id13, newExpiresAt);
9392
9472
  if (!updated) {
9393
9473
  throw new Error("Failed to update invitation");
9394
9474
  }
@@ -9702,8 +9782,8 @@ var registry2 = /* @__PURE__ */ new Map();
9702
9782
  function registerOAuthProvider(provider) {
9703
9783
  registry2.set(provider.id, provider);
9704
9784
  }
9705
- function getOAuthProvider(id12) {
9706
- return registry2.get(id12);
9785
+ function getOAuthProvider(id13) {
9786
+ return registry2.get(id13);
9707
9787
  }
9708
9788
  function getRegisteredProviders() {
9709
9789
  return [...registry2.values()];
@@ -10798,13 +10878,61 @@ async function persistNativeLogin(identity, params) {
10798
10878
  }, { context: "auth:oauth-native" });
10799
10879
  }
10800
10880
 
10881
+ // src/server/services/ops-token.service.ts
10882
+ init_ops_tokens_repository();
10883
+ import { createHash as createHash4, randomBytes } from "crypto";
10884
+ var OPS_TOKEN_PREFIX = "spfn_ops_";
10885
+ function hashOpsToken(token) {
10886
+ return createHash4("sha256").update(token).digest("hex");
10887
+ }
10888
+ async function issueOpsTokenService(name, scopes, expiresAt) {
10889
+ if (scopes.length === 0) {
10890
+ throw new Error("An ops token needs at least one scope ('*' grants all).");
10891
+ }
10892
+ const token = OPS_TOKEN_PREFIX + randomBytes(32).toString("hex");
10893
+ const record = await opsTokensRepository.create({
10894
+ name,
10895
+ tokenHash: hashOpsToken(token),
10896
+ scopes,
10897
+ expiresAt
10898
+ });
10899
+ return { token, record };
10900
+ }
10901
+ async function verifyOpsTokenService(token) {
10902
+ if (!token.startsWith(OPS_TOKEN_PREFIX)) {
10903
+ return null;
10904
+ }
10905
+ const record = await opsTokensRepository.findByTokenHash(hashOpsToken(token));
10906
+ if (!record) {
10907
+ return null;
10908
+ }
10909
+ if (record.revokedAt !== null) {
10910
+ return null;
10911
+ }
10912
+ if (record.expiresAt !== null && /* @__PURE__ */ new Date() > record.expiresAt) {
10913
+ return null;
10914
+ }
10915
+ opsTokensRepository.updateLastUsedById(record.id).catch((err) => authLogger.service.error("Failed to update ops token lastUsedAt", err));
10916
+ return {
10917
+ tokenId: record.id,
10918
+ name: record.name,
10919
+ scopes: record.scopes
10920
+ };
10921
+ }
10922
+ async function revokeOpsTokenService(id13) {
10923
+ return await opsTokensRepository.revokeById(id13);
10924
+ }
10925
+ async function listOpsTokensService() {
10926
+ return await opsTokensRepository.list();
10927
+ }
10928
+
10801
10929
  // src/server/routes/auth/index.ts
10802
10930
  init_esm();
10803
10931
  import { Transactional } from "@spfn/core/db";
10804
10932
  import { rateLimitPolicy } from "@spfn/core/middleware";
10805
10933
 
10806
10934
  // src/server/lib/rate-limit-keys.ts
10807
- import { createHash as createHash4 } from "crypto";
10935
+ import { createHash as createHash5 } from "crypto";
10808
10936
  import { getClientIp } from "@spfn/core/middleware";
10809
10937
  async function readJsonBody(c) {
10810
10938
  try {
@@ -10844,7 +10972,7 @@ function idTokenKey(body) {
10844
10972
  if (typeof body.idToken !== "string" || !body.idToken) {
10845
10973
  return void 0;
10846
10974
  }
10847
- return `tok:${createHash4("sha256").update(body.idToken).digest("hex")}`;
10975
+ return `tok:${createHash5("sha256").update(body.idToken).digest("hex")}`;
10848
10976
  }
10849
10977
  function byIpAndIdToken(options = {}) {
10850
10978
  return async (c) => {
@@ -11086,7 +11214,7 @@ import {
11086
11214
  } from "@spfn/auth/errors";
11087
11215
 
11088
11216
  // src/server/client-proof/refusal.ts
11089
- import { randomBytes } from "crypto";
11217
+ import { randomBytes as randomBytes2 } from "crypto";
11090
11218
 
11091
11219
  // src/server/client-proof/canonical-json.ts
11092
11220
  var CanonicalJsonError = class extends Error {
@@ -11099,13 +11227,13 @@ var CanonicalJsonError = class extends Error {
11099
11227
  var INT64_MIN = -(2n ** 63n);
11100
11228
  var INT64_MAX = 2n ** 63n - 1n;
11101
11229
  function parseCanonicalJson(bytes) {
11102
- let text12;
11230
+ let text13;
11103
11231
  try {
11104
- text12 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
11232
+ text13 = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
11105
11233
  } catch {
11106
11234
  throw new CanonicalJsonError("INVALID_UTF8");
11107
11235
  }
11108
- const parser = new Parser(text12);
11236
+ const parser = new Parser(text13);
11109
11237
  const value = parser.parseValue();
11110
11238
  parser.skipWhitespace();
11111
11239
  if (!parser.atEnd()) {
@@ -11126,8 +11254,8 @@ function isCanonicalBytes(bytes, value) {
11126
11254
  return true;
11127
11255
  }
11128
11256
  var Parser = class {
11129
- constructor(text12) {
11130
- this.text = text12;
11257
+ constructor(text13) {
11258
+ this.text = text13;
11131
11259
  }
11132
11260
  pos = 0;
11133
11261
  atEnd() {
@@ -11444,7 +11572,7 @@ var HTTP_STATUS = {
11444
11572
  CONTRACT_UNSUPPORTED: 409
11445
11573
  };
11446
11574
  function newHexId() {
11447
- return randomBytes(16).toString("hex");
11575
+ return randomBytes2(16).toString("hex");
11448
11576
  }
11449
11577
  var ClientProofRefusal = class _ClientProofRefusal {
11450
11578
  constructor(code, message) {
@@ -11546,11 +11674,11 @@ function contractViolation(message) {
11546
11674
  }
11547
11675
 
11548
11676
  // src/server/client-proof/contract-bundle.ts
11549
- import { createHash as createHash6 } from "crypto";
11677
+ import { createHash as createHash7 } from "crypto";
11550
11678
  init_types();
11551
11679
 
11552
11680
  // src/server/client-proof/proof.ts
11553
- import { createHash as createHash5, createPrivateKey, createPublicKey, sign, verify as verify2 } from "crypto";
11681
+ import { createHash as createHash6, createPrivateKey, createPublicKey, sign, verify as verify2 } from "crypto";
11554
11682
  var CLIENT_PROOF_PROFILE = "clientProofV1";
11555
11683
  var ABSENT_BODY_SHA256 = "0".repeat(64);
11556
11684
  var DEFAULT_REPLAY_WINDOW_MILLIS = 3e5;
@@ -11620,7 +11748,7 @@ function verifyClientProof(input, presentedProof, publicKey) {
11620
11748
  );
11621
11749
  }
11622
11750
  function sha256Hex(bytes) {
11623
- return createHash5("sha256").update(bytes).digest("hex");
11751
+ return createHash6("sha256").update(bytes).digest("hex");
11624
11752
  }
11625
11753
 
11626
11754
  // src/server/client-proof/admission.ts
@@ -12483,6 +12611,46 @@ function extractOTTHeader(header) {
12483
12611
  return header.substring(4);
12484
12612
  }
12485
12613
 
12614
+ // src/server/middleware/ops-token-auth.ts
12615
+ import { defineMiddleware as defineMiddleware6 } from "@spfn/core/route";
12616
+ import { ForbiddenError as ForbiddenError5, UnauthorizedError as UnauthorizedError4 } from "@spfn/core/errors";
12617
+ function getOpsToken(c) {
12618
+ return c.get("opsToken") ?? null;
12619
+ }
12620
+ var opsTokenAuth = defineMiddleware6("opsTokenAuth", async (c, next) => {
12621
+ const token = extractBearer(c.req.header("Authorization"));
12622
+ if (!token) {
12623
+ throw new UnauthorizedError4({ message: "Ops token required: Authorization: Bearer <token>" });
12624
+ }
12625
+ const verified = await verifyOpsTokenService(token);
12626
+ if (!verified) {
12627
+ throw new UnauthorizedError4({ message: "Invalid ops token" });
12628
+ }
12629
+ c.set("opsToken", verified);
12630
+ await next();
12631
+ }, { skips: ["auth"] });
12632
+ var requireOpsScope = defineMiddleware6(
12633
+ "opsScope",
12634
+ (...scopes) => async (c, next) => {
12635
+ const token = getOpsToken(c);
12636
+ if (!token) {
12637
+ throw new UnauthorizedError4({ message: "Ops token required: Authorization: Bearer <token>" });
12638
+ }
12639
+ const granted = new Set(token.scopes);
12640
+ const missing = scopes.filter((scope) => !granted.has(scope) && !granted.has("*"));
12641
+ if (missing.length > 0) {
12642
+ throw new ForbiddenError5({ message: `Ops token lacks scope: ${missing.join(", ")}` });
12643
+ }
12644
+ await next();
12645
+ }
12646
+ );
12647
+ function extractBearer(header) {
12648
+ if (!header || !header.startsWith("Bearer ")) {
12649
+ return null;
12650
+ }
12651
+ return header.substring(7);
12652
+ }
12653
+
12486
12654
  // src/server/routes/invitations/index.ts
12487
12655
  init_types();
12488
12656
  init_esm();
@@ -13271,7 +13439,7 @@ var oauthRouter = defineRouter4({
13271
13439
 
13272
13440
  // src/server/routes/admin/index.ts
13273
13441
  init_esm();
13274
- import { ForbiddenError as ForbiddenError5 } from "@spfn/core/errors";
13442
+ import { ForbiddenError as ForbiddenError6 } from "@spfn/core/errors";
13275
13443
  import { route as route5 } from "@spfn/core/route";
13276
13444
  var listRoles = route5.get("/_auth/admin/roles").input({
13277
13445
  query: Type.Object({
@@ -13341,11 +13509,11 @@ var updateUserRole = route5.patch("/_auth/admin/users/:userId/role").input({
13341
13509
  const { params, body } = await c.data();
13342
13510
  const auth = getAuth(c);
13343
13511
  if (params.userId === Number(auth.userId)) {
13344
- throw new ForbiddenError5({ message: "Cannot change your own role" });
13512
+ throw new ForbiddenError6({ message: "Cannot change your own role" });
13345
13513
  }
13346
13514
  const targetRole = await getUserRole(params.userId);
13347
13515
  if (targetRole === "superadmin") {
13348
- throw new ForbiddenError5({ message: "Cannot modify superadmin role" });
13516
+ throw new ForbiddenError6({ message: "Cannot modify superadmin role" });
13349
13517
  }
13350
13518
  await assertCanAssignRole(auth.userId, body.roleId);
13351
13519
  await updateUserService(params.userId, { roleId: body.roleId });
@@ -13400,6 +13568,64 @@ var deletionRouter = defineRouter5({
13400
13568
  cancelAccountDeletion
13401
13569
  });
13402
13570
 
13571
+ // src/server/routes/ops-tokens/index.ts
13572
+ init_esm();
13573
+ import { route as route7 } from "@spfn/core/route";
13574
+ import { BadRequestError as BadRequestError2, NotFoundError as NotFoundError4 } from "@spfn/core/errors";
13575
+ var MAX_EXPIRY_DAYS = 36500;
13576
+ function toSummary(record) {
13577
+ return {
13578
+ id: Number(record.id),
13579
+ name: record.name,
13580
+ scopes: record.scopes,
13581
+ expiresAt: record.expiresAt ? record.expiresAt.toISOString() : null,
13582
+ revokedAt: record.revokedAt ? record.revokedAt.toISOString() : null,
13583
+ lastUsedAt: record.lastUsedAt ? record.lastUsedAt.toISOString() : null,
13584
+ createdAt: record.createdAt ? record.createdAt.toISOString() : null
13585
+ };
13586
+ }
13587
+ var issueOpsToken = route7.post("/_auth/ops-tokens").input({
13588
+ body: Type.Object({
13589
+ name: Type.String({ minLength: 1, description: "Operator-facing label" }),
13590
+ scopes: Type.Array(Type.String({ minLength: 1 }), {
13591
+ minItems: 1,
13592
+ description: "Scopes the token grants ('*' grants all)"
13593
+ }),
13594
+ expiresInDays: Type.Optional(Type.Union([
13595
+ Type.Number({ exclusiveMinimum: 0, maximum: MAX_EXPIRY_DAYS }),
13596
+ Type.Null()
13597
+ ], {
13598
+ description: `Days until expiry, up to ${MAX_EXPIRY_DAYS}; null issues a non-expiring token`
13599
+ }))
13600
+ })
13601
+ }).use([authenticate, requireRole("admin", "superadmin")]).handler(async (c) => {
13602
+ const { body } = await c.data();
13603
+ const expiresInDays = body.expiresInDays ?? null;
13604
+ const expiresAt = expiresInDays === null ? null : new Date(Date.now() + expiresInDays * 24 * 60 * 60 * 1e3);
13605
+ if (expiresAt && Number.isNaN(expiresAt.getTime())) {
13606
+ throw new BadRequestError2({
13607
+ message: `expiresInDays takes 1 to ${MAX_EXPIRY_DAYS} days, or null for no expiry.`
13608
+ });
13609
+ }
13610
+ const { token, record } = await issueOpsTokenService(body.name, body.scopes, expiresAt);
13611
+ return { token, opsToken: toSummary(record) };
13612
+ });
13613
+ var listOpsTokens = route7.get("/_auth/ops-tokens").use([authenticate, requireRole("admin", "superadmin")]).handler(async () => {
13614
+ return { opsTokens: (await listOpsTokensService()).map(toSummary) };
13615
+ });
13616
+ var revokeOpsToken = route7.delete("/_auth/ops-tokens/:id").input({
13617
+ params: Type.Object({
13618
+ id: Type.Number({ description: "Ops token id" })
13619
+ })
13620
+ }).use([authenticate, requireRole("admin", "superadmin")]).handler(async (c) => {
13621
+ const { params } = await c.data();
13622
+ const record = await revokeOpsTokenService(params.id);
13623
+ if (!record) {
13624
+ throw new NotFoundError4({ message: `No ops token with id ${params.id} to revoke.` });
13625
+ }
13626
+ return { opsToken: toSummary(record) };
13627
+ });
13628
+
13403
13629
  // src/server/routes/index.ts
13404
13630
  var mainAuthRouter = defineRouter6({
13405
13631
  // Auth routes
@@ -13451,7 +13677,11 @@ var mainAuthRouter = defineRouter6({
13451
13677
  createAdminRole,
13452
13678
  updateAdminRole,
13453
13679
  deleteAdminRole,
13454
- updateUserRole
13680
+ updateUserRole,
13681
+ // Ops token routes (admin only)
13682
+ issueOpsToken,
13683
+ listOpsTokens,
13684
+ revokeOpsToken
13455
13685
  });
13456
13686
 
13457
13687
  // src/server.ts
@@ -13827,6 +14057,7 @@ export {
13827
14057
  KEY_FINGERPRINT_PREFIX_LENGTH,
13828
14058
  KEY_PLATFORM,
13829
14059
  KeysRepository,
14060
+ OpsTokensRepository,
13830
14061
  PURGE_STRATEGIES,
13831
14062
  PasswordSchema,
13832
14063
  PermissionsRepository,
@@ -13909,6 +14140,7 @@ export {
13909
14140
  getLocale,
13910
14141
  getOAuthProvider,
13911
14142
  getOneTimeTokenManager,
14143
+ getOpsToken,
13912
14144
  getOptionalAuth,
13913
14145
  getPendingDeletionInfo,
13914
14146
  getRegisteredProviders,
@@ -13942,10 +14174,12 @@ export {
13942
14174
  isGoogleOAuthEnabled,
13943
14175
  isOAuthProviderEnabled,
13944
14176
  issueOneTimeTokenService,
14177
+ issueOpsTokenService,
13945
14178
  kakaoProvider,
13946
14179
  keysRepository,
13947
14180
  listInvitations,
13948
14181
  listKeysService,
14182
+ listOpsTokensService,
13949
14183
  loginService,
13950
14184
  logoutService,
13951
14185
  matchOAuthCsrfCookies,
@@ -13956,6 +14190,9 @@ export {
13956
14190
  oauthUnlinkNotifyService,
13957
14191
  oauthUnlinkedEvent,
13958
14192
  oneTimeTokenAuth,
14193
+ opsTokenAuth,
14194
+ opsTokens,
14195
+ opsTokensRepository,
13959
14196
  optionalAuth,
13960
14197
  parseDuration,
13961
14198
  permissions,
@@ -13969,12 +14206,14 @@ export {
13969
14206
  requestAccountDeletionService,
13970
14207
  requireAnyPermission,
13971
14208
  requireEnabledProvider,
14209
+ requireOpsScope,
13972
14210
  requirePermissions,
13973
14211
  requireRole,
13974
14212
  resendInvitation,
13975
14213
  resolveAuthenticatedUser,
13976
14214
  revokeAllKeysService,
13977
14215
  revokeKeyService,
14216
+ revokeOpsTokenService,
13978
14217
  roleGuard,
13979
14218
  rolePermissions,
13980
14219
  rolePermissionsRepository,
@@ -14017,6 +14256,7 @@ export {
14017
14256
  verifyKeyFingerprint,
14018
14257
  verifyOAuthState,
14019
14258
  verifyOneTimeTokenService,
14259
+ verifyOpsTokenService,
14020
14260
  verifyPassword,
14021
14261
  verifyToken
14022
14262
  };