@revealui/auth 0.4.6 → 0.4.7
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/react/useSignIn.d.ts +1 -0
- package/dist/react/useSignIn.d.ts.map +1 -1
- package/dist/react/useSignIn.js +12 -2
- package/dist/server/audit-bridge.d.ts.map +1 -1
- package/dist/server/audit-bridge.js +13 -3
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +50 -20
- package/dist/server/session.d.ts.map +1 -1
- package/dist/server/session.js +15 -0
- package/package.json +11 -11
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../src/react/useSignIn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"useSignIn.d.ts","sourceRoot":"","sources":["../../src/react/useSignIn.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAuCxC,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,CACN,KAAK,EAAE,WAAW,KACf,OAAO,CACR;QAAE,OAAO,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,IAAI,CAAA;KAAE,GAC7B;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAChD;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,WAAW,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAC3D,CAAC;IACF,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,SAAS,IAAI,eAAe,CA2E3C"}
|
package/dist/react/useSignIn.js
CHANGED
|
@@ -27,9 +27,14 @@ const SignInUserSchema = z
|
|
|
27
27
|
function toUser(validated) {
|
|
28
28
|
return validated;
|
|
29
29
|
}
|
|
30
|
-
// Validation schemas for sign-in response
|
|
30
|
+
// Validation schemas for sign-in response. The error body carries both a
|
|
31
|
+
// human-readable `message` and a machine `code` (see createApplicationErrorResponseData
|
|
32
|
+
// in @revealui/core); `error` mirrors the code. All optional so a terse body
|
|
33
|
+
// still parses.
|
|
31
34
|
const SignInErrorResponseSchema = z.object({
|
|
32
35
|
error: z.string().optional(),
|
|
36
|
+
message: z.string().optional(),
|
|
37
|
+
code: z.string().optional(),
|
|
33
38
|
});
|
|
34
39
|
const SignInSuccessResponseSchema = z.object({
|
|
35
40
|
user: SignInUserSchema,
|
|
@@ -79,9 +84,14 @@ export function useSignIn() {
|
|
|
79
84
|
const json = await response.json();
|
|
80
85
|
if (!response.ok) {
|
|
81
86
|
const errorData = SignInErrorResponseSchema.parse(json);
|
|
87
|
+
// Prefer the human-readable `message` for display; fall back to the
|
|
88
|
+
// machine `error` code, then a generic default. `code` (e.g.
|
|
89
|
+
// 'EMAIL_NOT_VERIFIED') lets callers branch — e.g. offer a
|
|
90
|
+
// resend-verification action — without string-matching display copy.
|
|
82
91
|
return {
|
|
83
92
|
success: false,
|
|
84
|
-
error: errorData.error || 'Failed to sign in',
|
|
93
|
+
error: errorData.message || errorData.error || 'Failed to sign in',
|
|
94
|
+
code: errorData.code,
|
|
85
95
|
};
|
|
86
96
|
}
|
|
87
97
|
// Check for MFA challenge before parsing as full success
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit-bridge.d.ts","sourceRoot":"","sources":["../../src/server/audit-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;
|
|
1
|
+
{"version":3,"file":"audit-bridge.d.ts","sourceRoot":"","sources":["../../src/server/audit-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAyCH;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,MAAM,EACd,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,IAAI,CAAC,CASf;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CASnF;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAUjF;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/E;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAShF;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,IAAI,CAAC,CAUf;AAED;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,IAAI,CAAC,CAUf"}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* via the AuditSystem from @revealui/security/server. Uses lazy import to
|
|
6
6
|
* avoid circular dependency issues at module load time.
|
|
7
7
|
*/
|
|
8
|
+
import { logger } from '@revealui/core/observability/logger';
|
|
8
9
|
/**
|
|
9
10
|
* Lazily resolve the global audit system from @revealui/security/server.
|
|
10
11
|
* Returns null if the module cannot be loaded (e.g. in test environments
|
|
@@ -20,15 +21,24 @@ async function getAudit() {
|
|
|
20
21
|
}
|
|
21
22
|
}
|
|
22
23
|
/**
|
|
23
|
-
* Internal helper - logs an audit event
|
|
24
|
-
* audit system is unavailable
|
|
24
|
+
* Internal helper - logs an audit event best-effort. Silently skips when the
|
|
25
|
+
* audit system is unavailable, and swallows (but logs) a write failure so the
|
|
26
|
+
* operation being audited - e.g. a login - never fails because its audit
|
|
27
|
+
* record could not be persisted.
|
|
25
28
|
*/
|
|
26
29
|
async function logAuditEvent(event) {
|
|
27
30
|
const auditSystem = await getAudit();
|
|
28
31
|
if (!auditSystem) {
|
|
29
32
|
return;
|
|
30
33
|
}
|
|
31
|
-
|
|
34
|
+
try {
|
|
35
|
+
await auditSystem.log(event);
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
logger.error('Failed to write audit event', error instanceof Error ? error : undefined, {
|
|
39
|
+
type: event.type,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
32
42
|
}
|
|
33
43
|
/**
|
|
34
44
|
* Record a successful login to the audit trail.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAQ,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/server/auth.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAQ,MAAM,aAAa,CAAC;AAUpE;;;;;;;GAOG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,OAAO,CAAC,YAAY,CAAC,CAyLvB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAoBtD;AAED;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAC1B,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;IACR,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,IAAI,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACA,OAAO,CAAC,YAAY,CAAC,CAoOvB"}
|
package/dist/server/auth.js
CHANGED
|
@@ -6,9 +6,10 @@
|
|
|
6
6
|
import { createHash, randomBytes } from 'node:crypto';
|
|
7
7
|
import { logger } from '@revealui/core/observability/logger';
|
|
8
8
|
import { getClient } from '@revealui/db/client';
|
|
9
|
-
import { oauthAccounts, users } from '@revealui/db/schema';
|
|
9
|
+
import { accountMemberships, accounts, oauthAccounts, users } from '@revealui/db/schema';
|
|
10
10
|
import bcrypt from 'bcryptjs';
|
|
11
11
|
import { and, eq, isNull } from 'drizzle-orm';
|
|
12
|
+
import { auditLoginFailure, auditLoginSuccess } from './audit-bridge.js';
|
|
12
13
|
import { clearFailedAttempts, isAccountLocked, recordFailedAttempt } from './brute-force.js';
|
|
13
14
|
import { validatePasswordStrength } from './password-validation.js';
|
|
14
15
|
import { checkRateLimit } from './rate-limit.js';
|
|
@@ -85,22 +86,25 @@ export async function signIn(email, password, options) {
|
|
|
85
86
|
}
|
|
86
87
|
// Always return same error message to prevent user enumeration
|
|
87
88
|
const invalidCredentialsMessage = 'Invalid email or password';
|
|
88
|
-
|
|
89
|
+
// Record a failed credential attempt: bump the brute-force counter AND
|
|
90
|
+
// land a failed-login receipt in the audit trail. recordFailedAttempt only
|
|
91
|
+
// feeds lockout accounting; without the audit emit a failed sign-in leaves
|
|
92
|
+
// no receipt. auditLoginFailure is best-effort and never throws.
|
|
93
|
+
const failInvalidCredentials = async () => {
|
|
89
94
|
await recordFailedAttempt(email);
|
|
95
|
+
await auditLoginFailure(email, options?.ipAddress ?? 'unknown', options?.userAgent ?? 'unknown', 'invalid_credentials');
|
|
90
96
|
return {
|
|
91
97
|
success: false,
|
|
92
98
|
reason: 'invalid_credentials',
|
|
93
99
|
error: invalidCredentialsMessage,
|
|
94
100
|
};
|
|
101
|
+
};
|
|
102
|
+
if (!user) {
|
|
103
|
+
return failInvalidCredentials();
|
|
95
104
|
}
|
|
96
105
|
// Check if user has a password (not OAuth-only user)
|
|
97
106
|
if (!user.password) {
|
|
98
|
-
|
|
99
|
-
return {
|
|
100
|
-
success: false,
|
|
101
|
-
reason: 'invalid_credentials',
|
|
102
|
-
error: invalidCredentialsMessage,
|
|
103
|
-
};
|
|
107
|
+
return failInvalidCredentials();
|
|
104
108
|
}
|
|
105
109
|
// Verify password hash
|
|
106
110
|
let isValid;
|
|
@@ -109,20 +113,10 @@ export async function signIn(email, password, options) {
|
|
|
109
113
|
}
|
|
110
114
|
catch {
|
|
111
115
|
logger.error('Error comparing password');
|
|
112
|
-
|
|
113
|
-
return {
|
|
114
|
-
success: false,
|
|
115
|
-
reason: 'invalid_credentials',
|
|
116
|
-
error: invalidCredentialsMessage,
|
|
117
|
-
};
|
|
116
|
+
return failInvalidCredentials();
|
|
118
117
|
}
|
|
119
118
|
if (!isValid) {
|
|
120
|
-
|
|
121
|
-
return {
|
|
122
|
-
success: false,
|
|
123
|
-
reason: 'invalid_credentials',
|
|
124
|
-
error: invalidCredentialsMessage,
|
|
125
|
-
};
|
|
119
|
+
return failInvalidCredentials();
|
|
126
120
|
}
|
|
127
121
|
// Successful login - clear failed attempts
|
|
128
122
|
await clearFailedAttempts(email);
|
|
@@ -164,6 +158,10 @@ export async function signIn(email, password, options) {
|
|
|
164
158
|
error: 'Failed to create session',
|
|
165
159
|
};
|
|
166
160
|
}
|
|
161
|
+
// A fresh session was minted: the login succeeded. Land a success receipt
|
|
162
|
+
// in the audit trail (best-effort; auditLoginSuccess never throws, so an
|
|
163
|
+
// audit-write failure cannot fail the login).
|
|
164
|
+
await auditLoginSuccess(user.id, options?.ipAddress ?? 'unknown', options?.userAgent ?? 'unknown');
|
|
167
165
|
// Check if password rotation is required (e.g., bootstrapped admin accounts)
|
|
168
166
|
if (user.mustRotatePassword) {
|
|
169
167
|
return {
|
|
@@ -396,6 +394,38 @@ export async function signUp(email, password, name, options) {
|
|
|
396
394
|
error: 'Failed to create session',
|
|
397
395
|
};
|
|
398
396
|
}
|
|
397
|
+
// Provision a personal billing account + owner membership so a hosted tenant
|
|
398
|
+
// exists from signup. Best-effort: the Stripe billing webhook
|
|
399
|
+
// (ensureHostedAccount) is idempotent on an active membership and backfills
|
|
400
|
+
// this if it fails here, so a transient error never blocks signup. Skipped on
|
|
401
|
+
// self-hosted (Forge) deployments — single-tenant, no per-user accounts (mode
|
|
402
|
+
// detected by the license signing key, as in apps/server validate-startup).
|
|
403
|
+
if (process.env.REVEALUI_LICENSE_PRIVATE_KEY) {
|
|
404
|
+
try {
|
|
405
|
+
const accountId = crypto.randomUUID();
|
|
406
|
+
const now = new Date();
|
|
407
|
+
await db.insert(accounts).values({
|
|
408
|
+
id: accountId,
|
|
409
|
+
name: `${user.name || 'RevealUI'} Workspace`,
|
|
410
|
+
slug: `acct-${accountId}`,
|
|
411
|
+
status: 'active',
|
|
412
|
+
createdAt: now,
|
|
413
|
+
updatedAt: now,
|
|
414
|
+
});
|
|
415
|
+
await db.insert(accountMemberships).values({
|
|
416
|
+
id: crypto.randomUUID(),
|
|
417
|
+
accountId,
|
|
418
|
+
userId: user.id,
|
|
419
|
+
role: 'owner',
|
|
420
|
+
status: 'active',
|
|
421
|
+
createdAt: now,
|
|
422
|
+
updatedAt: now,
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
logger.error('Failed to provision personal account at signup (billing webhook will backfill)', undefined, { userId: user.id });
|
|
427
|
+
}
|
|
428
|
+
}
|
|
399
429
|
// Return the raw (unhashed) token so the caller can include it in the
|
|
400
430
|
// verification email link. The DB holds only the hash.
|
|
401
431
|
const userWithRawToken = { ...user, emailVerificationToken: rawEmailVerificationToken };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAQjD,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;CACzB;
|
|
1
|
+
{"version":3,"file":"session.d.ts","sourceRoot":"","sources":["../../src/server/session.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAQjD,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;IAC1B,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,yEAAyE;IACzE,cAAc,EAAE,OAAO,CAAC;CACzB;AAaD,mFAAmF;AACnF,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,OAAO,CAAC,oBAAoB,CAAC,GAAG,IAAI,CAEtF;AAED,qCAAqC;AACrC,wBAAgB,yBAAyB,IAAI,IAAI,CAEhD;AAMD,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,MAAM,GAAG,IAAI,CA0B3F;AAMD,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,IAAI,CAAC;CACZ;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI,GAAG,OAAO,CAI1E;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,cAAc,CAAC,EAAE,cAAc,GAC9B,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAgI7B;AAED;;;;;;GAMG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,IAAI,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC,GACA,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAmE9C;AAED;;;;;;;;;GASG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,+FAA+F;IAC/F,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,GACA,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAoC9C;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CA+BtE;AAED;;;;GAIG;AACH;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,MAAM,EAAE,MAAM,EACd,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC,CAyBf;AAED,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyBzE"}
|
package/dist/server/session.js
CHANGED
|
@@ -15,6 +15,8 @@ const DEFAULT_SESSION_BINDING = {
|
|
|
15
15
|
enforceIp: false,
|
|
16
16
|
warnOnIpChange: true,
|
|
17
17
|
};
|
|
18
|
+
/** Minimum interval between users.lastActiveAt writes for a given user. */
|
|
19
|
+
const LAST_ACTIVE_THROTTLE_MS = 60 * 60 * 1000;
|
|
18
20
|
let sessionBindingConfig = { ...DEFAULT_SESSION_BINDING };
|
|
19
21
|
/** Override session binding behaviour (useful for tests or strict deployments). */
|
|
20
22
|
export function configureSessionBinding(overrides) {
|
|
@@ -169,6 +171,19 @@ export async function getSession(headers, requestContext) {
|
|
|
169
171
|
// Log but don't fail - last activity update is not critical
|
|
170
172
|
logger.warn('Error updating last activity');
|
|
171
173
|
}
|
|
174
|
+
// Throttled users.lastActiveAt writer - fire-and-forget, never awaited,
|
|
175
|
+
// so auth latency is unaffected. Only touches the row when the stored
|
|
176
|
+
// value is null or older than the throttle window, keeping write volume
|
|
177
|
+
// to roughly one row-update per active user per hour instead of one per
|
|
178
|
+
// request.
|
|
179
|
+
if (!user.lastActiveAt || Date.now() - user.lastActiveAt.getTime() > LAST_ACTIVE_THROTTLE_MS) {
|
|
180
|
+
db.update(users)
|
|
181
|
+
.set({ lastActiveAt: new Date() })
|
|
182
|
+
.where(eq(users.id, user.id))
|
|
183
|
+
.catch(() => {
|
|
184
|
+
logger.warn('Error updating user lastActiveAt');
|
|
185
|
+
});
|
|
186
|
+
}
|
|
172
187
|
return {
|
|
173
188
|
session,
|
|
174
189
|
user,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@revealui/auth",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.7",
|
|
4
4
|
"description": "Database-backed session auth for Hono and Next.js — bcrypt, OAuth, brute-force protection, rate limiting, password reset. Ships with RevealUI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"auth",
|
|
@@ -10,26 +10,26 @@
|
|
|
10
10
|
],
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@simplewebauthn/server": "^13.3.
|
|
13
|
+
"@simplewebauthn/server": "^13.3.2",
|
|
14
14
|
"bcryptjs": "^3.0.3",
|
|
15
15
|
"drizzle-orm": "^0.45.2",
|
|
16
16
|
"zod": "^4.4.3",
|
|
17
|
-
"@revealui/config": "0.
|
|
18
|
-
"@revealui/contracts": "0.6.
|
|
19
|
-
"@revealui/core": "0.
|
|
20
|
-
"@revealui/db": "0.7.
|
|
21
|
-
"@revealui/security": "0.4.
|
|
17
|
+
"@revealui/config": "0.5.0",
|
|
18
|
+
"@revealui/contracts": "0.6.2",
|
|
19
|
+
"@revealui/core": "0.11.0",
|
|
20
|
+
"@revealui/db": "0.7.3",
|
|
21
|
+
"@revealui/security": "0.4.2"
|
|
22
22
|
},
|
|
23
23
|
"devDependencies": {
|
|
24
24
|
"@simplewebauthn/browser": "^13.3.0",
|
|
25
25
|
"@testing-library/react": "^16.3.2",
|
|
26
|
-
"@types/node": "^25.9.
|
|
26
|
+
"@types/node": "^25.9.4",
|
|
27
27
|
"@types/react": "^19.2.17",
|
|
28
|
-
"@vitest/coverage-v8": "^4.1.
|
|
29
|
-
"happy-dom": "^20.10.
|
|
28
|
+
"@vitest/coverage-v8": "^4.1.10",
|
|
29
|
+
"happy-dom": "^20.10.6",
|
|
30
30
|
"react": "^19.2.7",
|
|
31
31
|
"typescript": "^6.0.3",
|
|
32
|
-
"vitest": "^4.1.
|
|
32
|
+
"vitest": "^4.1.10",
|
|
33
33
|
"@revealui/dev": "0.1.0"
|
|
34
34
|
},
|
|
35
35
|
"engines": {
|