@happyvertical/smrt-users 0.42.3 → 0.42.5

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.
@@ -0,0 +1,24 @@
1
+ import { SmrtCollection } from '@happyvertical/smrt-core';
2
+ import { UsersCliAuthApproveLimit } from '../models/CliAuthApproveLimit.js';
3
+ export type CliAuthApproveReservation = {
4
+ allowed: true;
5
+ windowStartedAt: string;
6
+ } | {
7
+ allowed: false;
8
+ retryAfterSeconds: number;
9
+ };
10
+ export declare class UsersCliAuthApproveLimitCollection extends SmrtCollection<UsersCliAuthApproveLimit> {
11
+ static readonly _itemClass: typeof UsersCliAuthApproveLimit;
12
+ /**
13
+ * Atomically reserve one attempt across every process using this database.
14
+ * Failed attempts retain their reservation; successful attempts release it.
15
+ */
16
+ reserveAttempt(input: {
17
+ maxAttempts: number;
18
+ userId: string;
19
+ windowMs: number;
20
+ }): Promise<CliAuthApproveReservation>;
21
+ /** Release the reservation for an attempt that did not fail authentication. */
22
+ releaseAttempt(userId: string, windowStartedAt: string): Promise<void>;
23
+ }
24
+ //# sourceMappingURL=CliAuthApproveLimitCollection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CliAuthApproveLimitCollection.d.ts","sourceRoot":"","sources":["../../src/collections/CliAuthApproveLimitCollection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,MAAM,MAAM,yBAAyB,GACjC;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,eAAe,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,OAAO,EAAE,KAAK,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC;AAElD,qBAAa,kCAAmC,SAAQ,cAAc,CAAC,wBAAwB,CAAC;IAC9F,MAAM,CAAC,QAAQ,CAAC,UAAU,kCAA4B;IAEtD;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE;QAC1B,WAAW,EAAE,MAAM,CAAC;QACpB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAgEtC,+EAA+E;IACzE,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAoB7E"}
@@ -1,7 +1,41 @@
1
1
  import { SmrtCollection } from '@happyvertical/smrt-core';
2
2
  import { UsersCliAuthRequest } from '../models/CliAuthRequest.js';
3
+ export interface ApprovePendingCliAuthRequestInput {
4
+ approvedBy: string;
5
+ ipAddress?: string;
6
+ sessionTtlSeconds: number;
7
+ tenantId: string;
8
+ userAgent?: string;
9
+ userCode: string;
10
+ userId: string;
11
+ }
12
+ export interface ApprovedCliAuthRequestSnapshot {
13
+ approvedAt: Date;
14
+ id: string;
15
+ sessionId: string;
16
+ tenantId: string;
17
+ userId: string;
18
+ }
3
19
  export declare class UsersCliAuthRequestCollection extends SmrtCollection<UsersCliAuthRequest> {
4
20
  static readonly _itemClass: typeof UsersCliAuthRequest;
21
+ /**
22
+ * Atomically approve one pending request and mint its bearer session.
23
+ *
24
+ * The session is created inside the same transaction as the conditional
25
+ * pending-to-approved transition. If another approver wins, or persisting
26
+ * the approval fails, throwing rolls the losing session back with the
27
+ * request write so no usable orphan credential can remain.
28
+ */
29
+ approvePendingRequest(input: ApprovePendingCliAuthRequestInput): Promise<ApprovedCliAuthRequestSnapshot | null>;
30
+ /**
31
+ * Atomically consume the bearer session attached to an approved request.
32
+ *
33
+ * The conditional update is the arbiter: concurrent exchangers may observe
34
+ * the same candidate, but only one can change `approved` to `consumed` while
35
+ * matching the same session id. The winning transaction returns the token
36
+ * from its locked candidate and clears it from durable storage.
37
+ */
38
+ consumeApprovedSession(deviceCodeHash: string): Promise<string | null>;
5
39
  /**
6
40
  * Look up a pending or completed request by the short user code shown in the CLI.
7
41
  */
@@ -11,7 +45,7 @@ export declare class UsersCliAuthRequestCollection extends SmrtCollection<UsersC
11
45
  */
12
46
  findByDeviceCodeHash(deviceCodeHash: string): Promise<UsersCliAuthRequest | null>;
13
47
  /**
14
- * Delete expired pending requests (cleanup job).
48
+ * Delete expired pending, lazily-expired, or already-consumed requests.
15
49
  *
16
50
  * Scheduled by the framework retention sweep (#2375); `expiresAt` carries an
17
51
  * index for this predicate.
@@ -1 +1 @@
1
- {"version":3,"file":"CliAuthRequestCollection.d.ts","sourceRoot":"","sources":["../../src/collections/CliAuthRequestCollection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAElE,qBAAa,6BAA8B,SAAQ,cAAc,CAAC,mBAAmB,CAAC;IACpF,MAAM,CAAC,QAAQ,CAAC,UAAU,6BAAuB;IAEjD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQ3E;;OAEG;IACG,oBAAoB,CACxB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQtC;;;;;;;;;OASG;IACG,aAAa,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAwBzE;AAED,OAAO,EAAE,6BAA6B,IAAI,wBAAwB,EAAE,CAAC"}
1
+ {"version":3,"file":"CliAuthRequestCollection.d.ts","sourceRoot":"","sources":["../../src/collections/CliAuthRequestCollection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGlE,MAAM,WAAW,iCAAiC;IAChD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,8BAA8B;IAC7C,UAAU,EAAE,IAAI,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAID,qBAAa,6BAA8B,SAAQ,cAAc,CAAC,mBAAmB,CAAC;IACpF,MAAM,CAAC,QAAQ,CAAC,UAAU,6BAAuB;IAEjD;;;;;;;OAOG;IACG,qBAAqB,CACzB,KAAK,EAAE,iCAAiC,GACvC,OAAO,CAAC,8BAA8B,GAAG,IAAI,CAAC;IAgEjD;;;;;;;OAOG;IACG,sBAAsB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAiC5E;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQ3E;;OAEG;IACG,oBAAoB,CACxB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAQtC;;;;;;;;;OASG;IACG,aAAa,CAAC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;CAyBzE;AAED,OAAO,EAAE,6BAA6B,IAAI,wBAAwB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { $ as MembershipCollection, A as UserEmailKeyBackfillError, B as PermissionCatalogService, C as decodeOidcTransaction, Ct as UserStatus, E as resolveOidcProviderConfig, F as TenantHierarchyError, G as syncPermissionCatalog, H as deriveOperationPermissionSlug, I as MAX_TENANT_HIERARCHY_DEPTH, J as Role, K as RolePermission, L as Tenant, M as TenantPermissionOverrideCollection, N as TenantPermissionOverride, O as OidcProvisioningError, P as TenantCollection, Q as MembershipOverride, R as DEFAULT_ROLE_PERMISSION_PATTERNS, S as OidcLoginService, St as TenantStatus, T as getUsersOidcConfig, Tt as UsersCliAuthRequest, U as normalizeOperationPermissionAction, V as deriveOperationPermissionCollectionName, W as registerPermissionDefinitions, X as Permission, Y as PermissionCollection, Z as MembershipOverrideCollection, _ as readMobileBearerToken, _t as DEFAULT_TENANT_POLICY, a as TerminalAuthRateLimitError, at as GroupCollection, b as PermissionResolver, bt as SessionStatus, c as assertOperationPermission, ct as isValidEmail, d as getCurrentSessionPermissionContext, dt as DEFAULT_SESSION_TTL, et as Membership, f as getRequestScopedDatabase, ft as Session, g as MobileAuthService, gt as DEFAULT_ROLE_SLUGS, h as MobileAuthError, ht as DEFAULT_ROLES, i as TerminalAuthError, it as GroupMember, j as backfillUserEmailKeys, k as UserCollection, l as checkOperationPermission, lt as normalizeEmail, m as withSessionPermissionContext, mt as AccessRequestStatus, n as DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, nt as GroupRole, o as TerminalAuthService, ot as Group, p as withPrincipalPermissionContext, pt as generateSessionId, q as RoleCollection, r as DEFAULT_CLI_SESSION_TTL_SECONDS, rt as GroupMemberCollection, s as OperationPermissionError, st as User, t as DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, tt as GroupRoleCollection, u as hasOperationPermission, ut as SessionCollection, v as validateMobileRedirectUri, vt as MembershipStatus, w as encodeOidcTransaction, wt as UsersCliAuthRequestCollection, x as OidcLoginError, xt as TenantPermissionEffect, y as SessionService, yt as OverrideEffect, z as RolePermissionCollection } from "./chunks/TerminalAuthService-Bg3s5wHA.js";
1
+ import { $ as MembershipCollection, A as UserEmailKeyBackfillError, B as PermissionCatalogService, C as decodeOidcTransaction, Ct as TenantStatus, E as resolveOidcProviderConfig, F as TenantHierarchyError, G as syncPermissionCatalog, H as deriveOperationPermissionSlug, I as MAX_TENANT_HIERARCHY_DEPTH, J as Role, K as RolePermission, L as Tenant, M as TenantPermissionOverrideCollection, N as TenantPermissionOverride, O as OidcProvisioningError, P as TenantCollection, Q as MembershipOverride, R as DEFAULT_ROLE_PERMISSION_PATTERNS, S as OidcLoginService, St as TenantPermissionEffect, T as getUsersOidcConfig, Tt as UsersCliAuthRequest, U as normalizeOperationPermissionAction, V as deriveOperationPermissionCollectionName, W as registerPermissionDefinitions, X as Permission, Y as PermissionCollection, Z as MembershipOverrideCollection, _ as readMobileBearerToken, _t as DEFAULT_ROLE_SLUGS, a as TerminalAuthRateLimitError, at as GroupCollection, b as PermissionResolver, bt as OverrideEffect, c as assertOperationPermission, ct as isValidEmail, d as getCurrentSessionPermissionContext, dt as SessionCollection, et as Membership, f as getRequestScopedDatabase, ft as DEFAULT_SESSION_TTL, g as MobileAuthService, gt as DEFAULT_ROLES, h as MobileAuthError, ht as AccessRequestStatus, i as TerminalAuthError, it as GroupMember, j as backfillUserEmailKeys, k as UserCollection, l as checkOperationPermission, lt as normalizeEmail, m as withSessionPermissionContext, mt as generateSessionId, n as DEFAULT_CLI_AUTH_REQUEST_TTL_SECONDS, nt as GroupRole, o as TerminalAuthService, ot as Group, p as withPrincipalPermissionContext, pt as Session, q as RoleCollection, r as DEFAULT_CLI_SESSION_TTL_SECONDS, rt as GroupMemberCollection, s as OperationPermissionError, st as User, t as DEFAULT_CLI_AUTH_POLL_INTERVAL_SECONDS, tt as GroupRoleCollection, u as hasOperationPermission, ut as UsersCliAuthRequestCollection, v as validateMobileRedirectUri, vt as DEFAULT_TENANT_POLICY, w as encodeOidcTransaction, wt as UserStatus, x as OidcLoginError, xt as SessionStatus, y as SessionService, yt as MembershipStatus, z as RolePermissionCollection } from "./chunks/TerminalAuthService-CAomvhMa.js";
2
2
  import { ObjectRegistry, SmrtCollection, SmrtObject, field, findManifestEntryByQualifiedName, isUniqueViolationError, registerRetentionTask, smrt, unregisterRetentionTask } from "@happyvertical/smrt-core";
3
3
  import { TenantScoped, tenantId } from "@happyvertical/smrt-tenancy";
4
4
  import { createLogger } from "@happyvertical/logger";
@@ -121,7 +121,7 @@ function registerUserRetentionTasks() {
121
121
  });
122
122
  registerRetentionTask({
123
123
  name: CLI_AUTH_RETENTION_TASK,
124
- description: "Delete expired pending CLI auth requests",
124
+ description: "Delete expired pending, lazily-expired, and consumed CLI auth requests",
125
125
  run: async (db, context) => {
126
126
  return (await UsersCliAuthRequestCollection.create({ db })).deleteExpired({ dryRun: context.dryRun });
127
127
  }
@@ -953,7 +953,7 @@ var MagicLinkService = class MagicLinkService {
953
953
  * The caller is responsible for emailing the token to the user.
954
954
  */
955
955
  async generate(email) {
956
- const { SignJWT } = await import("./chunks/TerminalAuthService-Bg3s5wHA.js").then((n) => n.D);
956
+ const { SignJWT } = await import("./chunks/TerminalAuthService-CAomvhMa.js").then((n) => n.D);
957
957
  const key = await this.getSigningKey();
958
958
  const nonce = crypto.randomUUID();
959
959
  const normalizedEmail = normalizeEmail(email);
@@ -982,7 +982,7 @@ var MagicLinkService = class MagicLinkService {
982
982
  * @throws {MagicLinkError} If the token is invalid, expired, or already used
983
983
  */
984
984
  async verify(token) {
985
- const { jwtVerify, errors } = await import("./chunks/TerminalAuthService-Bg3s5wHA.js").then((n) => n.D);
985
+ const { jwtVerify, errors } = await import("./chunks/TerminalAuthService-CAomvhMa.js").then((n) => n.D);
986
986
  const key = await this.getSigningKey();
987
987
  let payload;
988
988
  try {