@furystack/security 8.0.0 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/esm/errors/password-complexity-error.d.ts +5 -4
- package/esm/errors/password-complexity-error.d.ts.map +1 -1
- package/esm/errors/password-complexity-error.js +5 -4
- package/esm/errors/password-complexity-error.js.map +1 -1
- package/esm/errors/unauthenticated-error.d.ts +3 -1
- package/esm/errors/unauthenticated-error.d.ts.map +1 -1
- package/esm/errors/unauthenticated-error.js +3 -1
- package/esm/errors/unauthenticated-error.js.map +1 -1
- package/esm/models/password-credential.d.ts +3 -13
- package/esm/models/password-credential.d.ts.map +1 -1
- package/esm/models/password-credential.js +3 -1
- package/esm/models/password-credential.js.map +1 -1
- package/esm/models/password-reset-token.d.ts +5 -9
- package/esm/models/password-reset-token.d.ts.map +1 -1
- package/esm/models/password-reset-token.js +5 -0
- package/esm/models/password-reset-token.js.map +1 -1
- package/esm/password-complexity-rules/contains-lowercase.d.ts +2 -2
- package/esm/password-complexity-rules/contains-lowercase.js +2 -2
- package/esm/password-complexity-rules/contains-uppercase.d.ts +2 -2
- package/esm/password-complexity-rules/contains-uppercase.js +2 -2
- package/esm/password-complexity-rules/max-length.d.ts +1 -4
- package/esm/password-complexity-rules/max-length.d.ts.map +1 -1
- package/esm/password-complexity-rules/max-length.js +1 -4
- package/esm/password-complexity-rules/max-length.js.map +1 -1
- package/esm/password-complexity-rules/min-length.d.ts +1 -4
- package/esm/password-complexity-rules/min-length.d.ts.map +1 -1
- package/esm/password-complexity-rules/min-length.js +1 -4
- package/esm/password-complexity-rules/min-length.js.map +1 -1
- package/package.json +7 -7
- package/src/errors/password-complexity-error.ts +7 -4
- package/src/errors/unauthenticated-error.ts +3 -1
- package/src/models/password-credential.ts +5 -15
- package/src/models/password-reset-token.ts +5 -9
- package/src/password-complexity-rules/contains-lowercase.ts +2 -2
- package/src/password-complexity-rules/contains-uppercase.ts +2 -2
- package/src/password-complexity-rules/max-length.ts +1 -4
- package/src/password-complexity-rules/min-length.ts +1 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [8.0.1] - 2026-05-21
|
|
4
|
+
|
|
5
|
+
### 📚 Documentation
|
|
6
|
+
|
|
7
|
+
- Rewrote JSDoc on the error classes (`PasswordComplexityError`, `UnauthenticatedError`), the model types (`PasswordCredential`, `PasswordResetToken`), and the bundled password-complexity rules (`containsLowercase`, `containsUppercase`, `minLength`, `maxLength`) to follow the new value-test guidance: dropped restate-the-type narration, kept intent / trade-offs / constraints.
|
|
8
|
+
|
|
9
|
+
### ⬆️ Dependencies
|
|
10
|
+
|
|
11
|
+
- Bump dev `vitest` to `^4.1.5`.
|
|
12
|
+
- Bumped `@types/node` to `^25.9.1` and `vitest` to `^4.1.7`. No source changes — dev-tooling bump only.
|
|
13
|
+
|
|
3
14
|
## [8.0.0] - 2026-04-25
|
|
4
15
|
|
|
5
16
|
### 💥 Breaking Changes
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by password-setting flows when the candidate password fails one or
|
|
3
|
+
* more configured {@link PasswordComplexityRule}s. `result` carries the
|
|
4
|
+
* per-rule failures so callers can render targeted user feedback.
|
|
5
|
+
*/
|
|
1
6
|
export declare class PasswordComplexityError extends Error {
|
|
2
7
|
readonly result: Array<{
|
|
3
8
|
message: string;
|
|
4
9
|
rule: string;
|
|
5
10
|
}>;
|
|
6
|
-
/**
|
|
7
|
-
* @param result A detailed error result array
|
|
8
|
-
* @param message The Error message
|
|
9
|
-
*/
|
|
10
11
|
constructor(result: Array<{
|
|
11
12
|
message: string;
|
|
12
13
|
rule: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-complexity-error.d.ts","sourceRoot":"","sources":["../../src/errors/password-complexity-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"password-complexity-error.d.ts","sourceRoot":"","sources":["../../src/errors/password-complexity-error.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAE9B,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;gBAAhD,MAAM,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,EAChE,OAAO,CAAC,EAAE,MAAM;CAInB"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown by password-setting flows when the candidate password fails one or
|
|
3
|
+
* more configured {@link PasswordComplexityRule}s. `result` carries the
|
|
4
|
+
* per-rule failures so callers can render targeted user feedback.
|
|
5
|
+
*/
|
|
1
6
|
export class PasswordComplexityError extends Error {
|
|
2
7
|
result;
|
|
3
|
-
/**
|
|
4
|
-
* @param result A detailed error result array
|
|
5
|
-
* @param message The Error message
|
|
6
|
-
*/
|
|
7
8
|
constructor(result, message) {
|
|
8
9
|
super(message);
|
|
9
10
|
this.result = result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-complexity-error.js","sourceRoot":"","sources":["../../src/errors/password-complexity-error.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"password-complexity-error.js","sourceRoot":"","sources":["../../src/errors/password-complexity-error.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAE9B;IADlB,YACkB,MAAgD,EAChE,OAAgB;QAEhB,KAAK,CAAC,OAAO,CAAC,CAAA;QAHE,WAAM,GAAN,MAAM,CAA0C;IAIlE,CAAC;CACF"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Thrown when credential verification fails: bad username/password, expired
|
|
3
|
+
* password, or expired/invalid reset token. REST handlers should map this
|
|
4
|
+
* to a 401 response.
|
|
3
5
|
*/
|
|
4
6
|
export declare class UnauthenticatedError extends Error {
|
|
5
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unauthenticated-error.d.ts","sourceRoot":"","sources":["../../src/errors/unauthenticated-error.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"unauthenticated-error.d.ts","sourceRoot":"","sources":["../../src/errors/unauthenticated-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;CAAG"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Thrown when credential verification fails: bad username/password, expired
|
|
3
|
+
* password, or expired/invalid reset token. REST handlers should map this
|
|
4
|
+
* to a 401 response.
|
|
3
5
|
*/
|
|
4
6
|
export class UnauthenticatedError extends Error {
|
|
5
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unauthenticated-error.js","sourceRoot":"","sources":["../../src/errors/unauthenticated-error.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"unauthenticated-error.js","sourceRoot":"","sources":["../../src/errors/unauthenticated-error.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;CAAG"}
|
|
@@ -1,22 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Persisted password credential. `passwordHash` and `salt` are produced by
|
|
3
|
+
* the configured {@link PasswordHasher}; `creationDate` (ISO 8601 string)
|
|
4
|
+
* is the source of truth for password-expiration policies.
|
|
3
5
|
*/
|
|
4
6
|
export declare class PasswordCredential {
|
|
5
|
-
/**
|
|
6
|
-
* The unique name of the user
|
|
7
|
-
*/
|
|
8
7
|
userName: string;
|
|
9
|
-
/**
|
|
10
|
-
* The hashed password value
|
|
11
|
-
*/
|
|
12
8
|
passwordHash: string;
|
|
13
|
-
/**
|
|
14
|
-
* Salt value for password hashing // TODO
|
|
15
|
-
*/
|
|
16
9
|
salt: string;
|
|
17
|
-
/**
|
|
18
|
-
* The Creation date in ISO String format
|
|
19
|
-
*/
|
|
20
10
|
creationDate: string;
|
|
21
11
|
}
|
|
22
12
|
//# sourceMappingURL=password-credential.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-credential.d.ts","sourceRoot":"","sources":["../../src/models/password-credential.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"password-credential.d.ts","sourceRoot":"","sources":["../../src/models/password-credential.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,qBAAa,kBAAkB;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CAC7B"}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Persisted password credential. `passwordHash` and `salt` are produced by
|
|
3
|
+
* the configured {@link PasswordHasher}; `creationDate` (ISO 8601 string)
|
|
4
|
+
* is the source of truth for password-expiration policies.
|
|
3
5
|
*/
|
|
4
6
|
export class PasswordCredential {
|
|
5
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-credential.js","sourceRoot":"","sources":["../../src/models/password-credential.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"password-credential.js","sourceRoot":"","sources":["../../src/models/password-credential.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;CAK9B"}
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-use password reset token. `token` is the URL-safe identifier
|
|
3
|
+
* shared with the user (e.g. via email). `createdAt` (ISO 8601) is the
|
|
4
|
+
* expiration anchor honoured by `SecurityPolicyManager.hasTokenExpired`.
|
|
5
|
+
*/
|
|
1
6
|
export declare class PasswordResetToken {
|
|
2
|
-
/**
|
|
3
|
-
* The related user name
|
|
4
|
-
*/
|
|
5
7
|
userName: string;
|
|
6
|
-
/**
|
|
7
|
-
* The Token value - should be some kind of generated UUID that can be included e.g. in URLs
|
|
8
|
-
*/
|
|
9
8
|
token: string;
|
|
10
|
-
/**
|
|
11
|
-
* The creation date in an ISO datetime format
|
|
12
|
-
*/
|
|
13
9
|
createdAt: string;
|
|
14
10
|
}
|
|
15
11
|
//# sourceMappingURL=password-reset-token.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-reset-token.d.ts","sourceRoot":"","sources":["../../src/models/password-reset-token.ts"],"names":[],"mappings":"AAAA,qBAAa,kBAAkB;
|
|
1
|
+
{"version":3,"file":"password-reset-token.d.ts","sourceRoot":"","sources":["../../src/models/password-reset-token.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,qBAAa,kBAAkB;IACrB,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;CAC1B"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-use password reset token. `token` is the URL-safe identifier
|
|
3
|
+
* shared with the user (e.g. via email). `createdAt` (ISO 8601) is the
|
|
4
|
+
* expiration anchor honoured by `SecurityPolicyManager.hasTokenExpired`.
|
|
5
|
+
*/
|
|
1
6
|
export class PasswordResetToken {
|
|
2
7
|
}
|
|
3
8
|
//# sourceMappingURL=password-reset-token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"password-reset-token.js","sourceRoot":"","sources":["../../src/models/password-reset-token.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,kBAAkB;
|
|
1
|
+
{"version":3,"file":"password-reset-token.js","sourceRoot":"","sources":["../../src/models/password-reset-token.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,OAAO,kBAAkB;CAI9B"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Builds a complexity rule that requires at least `lowerCaseCount` lowercase
|
|
4
|
+
* characters. Diacritics are stripped before counting.
|
|
5
5
|
*/
|
|
6
6
|
export declare const createContainsLowercasePolicy: (lowerCaseCount: number) => PasswordComplexityRule;
|
|
7
7
|
//# sourceMappingURL=contains-lowercase.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Builds a complexity rule that requires at least `lowerCaseCount` lowercase
|
|
3
|
+
* characters. Diacritics are stripped before counting.
|
|
4
4
|
*/
|
|
5
5
|
export const createContainsLowercasePolicy = (lowerCaseCount) => ({
|
|
6
6
|
name: 'containsLowercase',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* Builds a complexity rule that requires at least `upperCaseCount` uppercase
|
|
4
|
+
* characters. Diacritics are stripped before counting (`Á` counts as `A`).
|
|
5
5
|
*/
|
|
6
6
|
export declare const createContainsUppercasePolicy: (upperCaseCount: number) => PasswordComplexityRule;
|
|
7
7
|
//# sourceMappingURL=contains-uppercase.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Builds a complexity rule that requires at least `upperCaseCount` uppercase
|
|
3
|
+
* characters. Diacritics are stripped before counting (`Á` counts as `A`).
|
|
4
4
|
*/
|
|
5
5
|
export const createContainsUppercasePolicy = (upperCaseCount) => ({
|
|
6
6
|
name: 'containsUppercase',
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js';
|
|
2
|
-
/**
|
|
3
|
-
* @param maxLength The maximum password length
|
|
4
|
-
* @returns The created Password Policy object
|
|
5
|
-
*/
|
|
2
|
+
/** Builds a complexity rule that fails when the password is longer than `maxLength`. */
|
|
6
3
|
export declare const createMaxLengthComplexityRule: (maxLength: number) => PasswordComplexityRule;
|
|
7
4
|
//# sourceMappingURL=max-length.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"max-length.d.ts","sourceRoot":"","sources":["../../src/password-complexity-rules/max-length.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAEnF
|
|
1
|
+
{"version":3,"file":"max-length.d.ts","sourceRoot":"","sources":["../../src/password-complexity-rules/max-length.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAEnF,wFAAwF;AACxF,eAAO,MAAM,6BAA6B,GAAI,WAAW,MAAM,KAAG,sBAShE,CAAA"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param maxLength The maximum password length
|
|
3
|
-
* @returns The created Password Policy object
|
|
4
|
-
*/
|
|
1
|
+
/** Builds a complexity rule that fails when the password is longer than `maxLength`. */
|
|
5
2
|
export const createMaxLengthComplexityRule = (maxLength) => ({
|
|
6
3
|
name: 'maxLength',
|
|
7
4
|
check: async (passwordString) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"max-length.js","sourceRoot":"","sources":["../../src/password-complexity-rules/max-length.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"max-length.js","sourceRoot":"","sources":["../../src/password-complexity-rules/max-length.ts"],"names":[],"mappings":"AAEA,wFAAwF;AACxF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,SAAiB,EAA0B,EAAE,CAAC,CAAC;IAC3F,IAAI,EAAE,WAAoB;IAC1B,KAAK,EAAE,KAAK,EAAE,cAAsB,EAAE,EAAE;QACtC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,SAAS,CAAA;QAClD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAA;QACpB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,kCAAkC,SAAS,mBAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAA;IAChH,CAAC;CACF,CAAC,CAAA"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js';
|
|
2
|
-
/**
|
|
3
|
-
* @param minLength The minimum password length
|
|
4
|
-
* @returns The created Password Policy object
|
|
5
|
-
*/
|
|
2
|
+
/** Builds a complexity rule that fails when the password is shorter than `minLength`. */
|
|
6
3
|
export declare const createMinLengthComplexityRule: (minLength: number) => PasswordComplexityRule;
|
|
7
4
|
//# sourceMappingURL=min-length.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"min-length.d.ts","sourceRoot":"","sources":["../../src/password-complexity-rules/min-length.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAEnF
|
|
1
|
+
{"version":3,"file":"min-length.d.ts","sourceRoot":"","sources":["../../src/password-complexity-rules/min-length.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAA;AAEnF,yFAAyF;AACzF,eAAO,MAAM,6BAA6B,GAAI,WAAW,MAAM,KAAG,sBAShE,CAAA"}
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param minLength The minimum password length
|
|
3
|
-
* @returns The created Password Policy object
|
|
4
|
-
*/
|
|
1
|
+
/** Builds a complexity rule that fails when the password is shorter than `minLength`. */
|
|
5
2
|
export const createMinLengthComplexityRule = (minLength) => ({
|
|
6
3
|
name: 'minLength',
|
|
7
4
|
check: async (passwordString) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"min-length.js","sourceRoot":"","sources":["../../src/password-complexity-rules/min-length.ts"],"names":[],"mappings":"AAEA
|
|
1
|
+
{"version":3,"file":"min-length.js","sourceRoot":"","sources":["../../src/password-complexity-rules/min-length.ts"],"names":[],"mappings":"AAEA,yFAAyF;AACzF,MAAM,CAAC,MAAM,6BAA6B,GAAG,CAAC,SAAiB,EAA0B,EAAE,CAAC,CAAC;IAC3F,IAAI,EAAE,WAAoB;IAC1B,KAAK,EAAE,KAAK,EAAE,cAAsB,EAAE,EAAE;QACtC,MAAM,OAAO,GAAG,cAAc,CAAC,MAAM,IAAI,SAAS,CAAA;QAClD,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,EAAE,OAAO,EAAE,CAAA;QACpB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mCAAmC,SAAS,mBAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAA;IACjH,CAAC;CACF,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@furystack/security",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.1",
|
|
4
4
|
"description": "Security, password management and authorization related stuff for FuryStack",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -37,16 +37,16 @@
|
|
|
37
37
|
"url": "https://github.com/furystack/furystack/issues"
|
|
38
38
|
},
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@furystack/core": "^17.
|
|
41
|
-
"@furystack/inject": "^13.0.
|
|
42
|
-
"@furystack/repository": "^11.0.
|
|
40
|
+
"@furystack/core": "^17.1.0",
|
|
41
|
+
"@furystack/inject": "^13.0.1",
|
|
42
|
+
"@furystack/repository": "^11.0.1"
|
|
43
43
|
},
|
|
44
44
|
"homepage": "https://github.com/furystack/furystack",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@furystack/utils": "^9.0.
|
|
47
|
-
"@types/node": "^25.
|
|
46
|
+
"@furystack/utils": "^9.0.1",
|
|
47
|
+
"@types/node": "^25.9.1",
|
|
48
48
|
"typescript": "^6.0.3",
|
|
49
|
-
"vitest": "^4.1.
|
|
49
|
+
"vitest": "^4.1.7"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": ">=22.0.0"
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Thrown by password-setting flows when the candidate password fails one or
|
|
5
|
+
* more configured {@link PasswordComplexityRule}s. `result` carries the
|
|
6
|
+
* per-rule failures so callers can render targeted user feedback.
|
|
7
|
+
*/
|
|
1
8
|
export class PasswordComplexityError extends Error {
|
|
2
|
-
/**
|
|
3
|
-
* @param result A detailed error result array
|
|
4
|
-
* @param message The Error message
|
|
5
|
-
*/
|
|
6
9
|
constructor(
|
|
7
10
|
public readonly result: Array<{ message: string; rule: string }>,
|
|
8
11
|
message?: string,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Thrown when credential verification fails: bad username/password, expired
|
|
3
|
+
* password, or expired/invalid reset token. REST handlers should map this
|
|
4
|
+
* to a 401 response.
|
|
3
5
|
*/
|
|
4
6
|
export class UnauthenticatedError extends Error {}
|
|
@@ -1,23 +1,13 @@
|
|
|
1
|
+
import type { PasswordHasher } from '../password-hasher.js'
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
|
-
*
|
|
4
|
+
* Persisted password credential. `passwordHash` and `salt` are produced by
|
|
5
|
+
* the configured {@link PasswordHasher}; `creationDate` (ISO 8601 string)
|
|
6
|
+
* is the source of truth for password-expiration policies.
|
|
3
7
|
*/
|
|
4
8
|
export class PasswordCredential {
|
|
5
|
-
/**
|
|
6
|
-
* The unique name of the user
|
|
7
|
-
*/
|
|
8
9
|
declare userName: string
|
|
9
|
-
/**
|
|
10
|
-
* The hashed password value
|
|
11
|
-
*/
|
|
12
10
|
declare passwordHash: string
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Salt value for password hashing // TODO
|
|
16
|
-
*/
|
|
17
11
|
declare salt: string
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* The Creation date in ISO String format
|
|
21
|
-
*/
|
|
22
12
|
declare creationDate: string
|
|
23
13
|
}
|
|
@@ -1,14 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single-use password reset token. `token` is the URL-safe identifier
|
|
3
|
+
* shared with the user (e.g. via email). `createdAt` (ISO 8601) is the
|
|
4
|
+
* expiration anchor honoured by `SecurityPolicyManager.hasTokenExpired`.
|
|
5
|
+
*/
|
|
1
6
|
export class PasswordResetToken {
|
|
2
|
-
/**
|
|
3
|
-
* The related user name
|
|
4
|
-
*/
|
|
5
7
|
declare userName: string
|
|
6
|
-
/**
|
|
7
|
-
* The Token value - should be some kind of generated UUID that can be included e.g. in URLs
|
|
8
|
-
*/
|
|
9
8
|
declare token: string
|
|
10
|
-
/**
|
|
11
|
-
* The creation date in an ISO datetime format
|
|
12
|
-
*/
|
|
13
9
|
declare createdAt: string
|
|
14
10
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Builds a complexity rule that requires at least `lowerCaseCount` lowercase
|
|
5
|
+
* characters. Diacritics are stripped before counting.
|
|
6
6
|
*/
|
|
7
7
|
export const createContainsLowercasePolicy = (lowerCaseCount: number): PasswordComplexityRule => ({
|
|
8
8
|
name: 'containsLowercase' as const,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Builds a complexity rule that requires at least `upperCaseCount` uppercase
|
|
5
|
+
* characters. Diacritics are stripped before counting (`Á` counts as `A`).
|
|
6
6
|
*/
|
|
7
7
|
export const createContainsUppercasePolicy = (upperCaseCount: number): PasswordComplexityRule => ({
|
|
8
8
|
name: 'containsUppercase' as const,
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js'
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @param maxLength The maximum password length
|
|
5
|
-
* @returns The created Password Policy object
|
|
6
|
-
*/
|
|
3
|
+
/** Builds a complexity rule that fails when the password is longer than `maxLength`. */
|
|
7
4
|
export const createMaxLengthComplexityRule = (maxLength: number): PasswordComplexityRule => ({
|
|
8
5
|
name: 'maxLength' as const,
|
|
9
6
|
check: async (passwordString: string) => {
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { PasswordComplexityRule } from '../models/password-complexity-rule.js'
|
|
2
2
|
|
|
3
|
-
/**
|
|
4
|
-
* @param minLength The minimum password length
|
|
5
|
-
* @returns The created Password Policy object
|
|
6
|
-
*/
|
|
3
|
+
/** Builds a complexity rule that fails when the password is shorter than `minLength`. */
|
|
7
4
|
export const createMinLengthComplexityRule = (minLength: number): PasswordComplexityRule => ({
|
|
8
5
|
name: 'minLength' as const,
|
|
9
6
|
check: async (passwordString: string) => {
|