@nodefony/security 10.0.0-alpha.5 → 10.0.0-alpha.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.
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorate.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.149.0/helpers/esm/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateMetadata.js
2
2
  function __decorateMetadata(k, v) {
3
3
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
4
  }
package/dist/index.js CHANGED
@@ -77,8 +77,8 @@ import SecurityUserPassword from "./nodefony/command/security-user-password.js";
77
77
  import SecurityToken from "./nodefony/command/security-token.js";
78
78
  import { createSecurityAdminApi, parseAuditQuery, registerSecurityAdminApi } from "./nodefony/src/admin/SecurityAdminApi.js";
79
79
  import { registerUserRevocationCascade } from "./nodefony/src/admin/userRevocationCascade.js";
80
- import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorateMetadata.js";
81
- import __decorate from "./_virtual/_@oxc-project_runtime@0.149.0/helpers/esm/decorate.js";
80
+ import __decorateMetadata from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
81
+ import __decorate from "./_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
82
82
  import { tokenStatusCriteria } from "./nodefony/src/token/tokenCriteria.js";
83
83
  import { AccessDeniedError } from "./nodefony/errors/AccessDeniedError.js";
84
84
  import "./nodefony/errors/index.js";
@@ -1,4 +1,5 @@
1
1
  import { CONSOLE_DATA_RUN_PROFILE, Command, askPasswordMasked } from "nodefony";
2
+ import { WeakPasswordError } from "@nodefony/user";
2
3
  //#region nodefony/command/security-user-add.ts
3
4
  const options = {
4
5
  runProfile: CONSOLE_DATA_RUN_PROFILE,
@@ -47,6 +48,13 @@ const AUTH_LOGIN_PATH = "/nodefony/security/api/auth/login";
47
48
  *
48
49
  * Le service `users` est posé par l'APPLICATION (cf `provisionUsers` du
49
50
  * template d'app) — absent = message actionnable, pas de stack.
51
+ *
52
+ * **Le mot de passe est soumis à la politique** (`PasswordPolicy`, posée d'office
53
+ * sur `UserService`) : longueur minimale (10 par défaut), mot de passe qui
54
+ * reprend l'identifiant du compte, motif répété de bout en bout, suite de
55
+ * touches, liste de l'application, et les ~10 000 mots de passe les plus
56
+ * courants. Un refus sort en **code non nul**, NOMME la règle enfreinte, et ne
57
+ * crée aucun compte — `--password abc` échoue, là où il réussissait.
50
58
  */
51
59
  var SecurityUserAdd = class extends Command {
52
60
  constructor(cli) {
@@ -135,11 +143,21 @@ var SecurityUserAdd = class extends Command {
135
143
  });
136
144
  roles = chosen.length > 0 ? chosen : [ROLE_BASE];
137
145
  } else roles = [ROLE_BASE];
138
- const user = await users.createUser({
139
- identifier,
140
- plainPassword: password,
141
- roles
142
- });
146
+ let user;
147
+ try {
148
+ user = await users.createUser({
149
+ identifier,
150
+ plainPassword: password,
151
+ roles
152
+ });
153
+ } catch (e) {
154
+ if (e instanceof WeakPasswordError) {
155
+ this.log(`${e.message}\n la politique se règle à l'application : \`new PasswordPolicy({ minLength, blocklist })\` posée sur \`users.passwordBlocklist\`.`, "ERROR");
156
+ process.exitCode = 1;
157
+ return this;
158
+ }
159
+ throw e;
160
+ }
143
161
  process.stdout.write(`\n${GREEN}✓ compte créé${RESET} — ${BOLD}${user.identifier}${RESET} ${DIM}(id ${user.id})${RESET}\n rôles : ${roles.join(" · ")}\n` + (opts.admin ? ` ${DIM}accès console Studio : /nodefony${RESET}\n` : "") + ` ${DIM}pour t'authentifier : POST ${AUTH_LOGIN_PATH}${RESET}\n ${DIM} body JSON {"username","password"} → cookie de session ; l'identité courante se relit sur GET /nodefony/security/api/auth/me${RESET}\n` + (opts.password ? ` ${YELLOW}⚠ mot de passe passé en argument — pense à purger l'historique shell${RESET}\n` : ""));
144
162
  return this;
145
163
  }
@@ -26,8 +26,11 @@ const RESET = "\x1B[0m";
26
26
  * Mot de passe : `--password` (visible dans l'historique shell — accepté pour
27
27
  * les scripts) ou PROMPT MASQUÉ en TTY, demandé deux fois. Le hachage est celui
28
28
  * du service (`UserService.changePassword` → Argon2id) : jamais de clair
29
- * persisté, et la liste de mots de passe interdits s'applique comme à la
30
- * création.
29
+ * persisté, et la POLITIQUE de mot de passe s'applique comme à la création —
30
+ * longueur minimale (10 par défaut), mot de passe qui reprend l'identifiant du
31
+ * compte, motif répété, suite de touches, liste de l'application, et les ~10 000
32
+ * mots de passe les plus courants. Un refus sort en code non nul et NOMME la
33
+ * règle enfreinte ; il ne crée ni ne modifie rien.
31
34
  *
32
35
  * 🔒 **Les sessions et les jetons du compte sont RÉVOQUÉS**, et ce n'est pas une
33
36
  * option : on change un mot de passe parce qu'il est compromis ou perdu, et
@@ -31,6 +31,13 @@ export declare const AUTH_LOGIN_PATH = "/nodefony/security/api/auth/login";
31
31
  *
32
32
  * Le service `users` est posé par l'APPLICATION (cf `provisionUsers` du
33
33
  * template d'app) — absent = message actionnable, pas de stack.
34
+ *
35
+ * **Le mot de passe est soumis à la politique** (`PasswordPolicy`, posée d'office
36
+ * sur `UserService`) : longueur minimale (10 par défaut), mot de passe qui
37
+ * reprend l'identifiant du compte, motif répété de bout en bout, suite de
38
+ * touches, liste de l'application, et les ~10 000 mots de passe les plus
39
+ * courants. Un refus sort en **code non nul**, NOMME la règle enfreinte, et ne
40
+ * crée aucun compte — `--password abc` échoue, là où il réussissait.
34
41
  */
35
42
  declare class SecurityUserAdd extends Command {
36
43
  #private;
@@ -12,8 +12,11 @@ import { CliKernel, Command } from "nodefony";
12
12
  * Mot de passe : `--password` (visible dans l'historique shell — accepté pour
13
13
  * les scripts) ou PROMPT MASQUÉ en TTY, demandé deux fois. Le hachage est celui
14
14
  * du service (`UserService.changePassword` → Argon2id) : jamais de clair
15
- * persisté, et la liste de mots de passe interdits s'applique comme à la
16
- * création.
15
+ * persisté, et la POLITIQUE de mot de passe s'applique comme à la création —
16
+ * longueur minimale (10 par défaut), mot de passe qui reprend l'identifiant du
17
+ * compte, motif répété, suite de touches, liste de l'application, et les ~10 000
18
+ * mots de passe les plus courants. Un refus sort en code non nul et NOMME la
19
+ * règle enfreinte ; il ne crée ni ne modifie rien.
17
20
  *
18
21
  * 🔒 **Les sessions et les jetons du compte sont RÉVOQUÉS**, et ce n'est pas une
19
22
  * option : on change un mot de passe parce qu'il est compromis ou perdu, et
@@ -183,7 +183,7 @@ curl -si http://localhost:5151/api/v1/whoami | grep -E "^(HTTP|WWW)"
183
183
  # HTTP/1.1 401 Unauthorized
184
184
  # WWW-Authenticate: Bearer
185
185
 
186
- # 2) Web — login BFF (compte dev seedé admin/admin) → cookie de session
186
+ # 2) Web — login BFF (compte dev seedé admin/nodefony-dev-42) → cookie de session
187
187
  curl -si -c /tmp/jar -H 'Content-Type: application/json' \
188
188
  -d '{"username":"admin","password":"admin"}' \
189
189
  http://localhost:5151/nodefony/security/api/auth/login | head -1
package/docs/firewall.md CHANGED
@@ -149,7 +149,7 @@ le fait pour toi.)
149
149
  curl -si http://localhost:5151/api/secure/account/me | head -1
150
150
  # HTTP/1.1 401 Unauthorized
151
151
 
152
- # 2) Login BFF (compte dev seedé admin/admin) → cookie de session
152
+ # 2) Login BFF (compte dev seedé admin/nodefony-dev-42) → cookie de session
153
153
  curl -si -c /tmp/jar -H 'Content-Type: application/json' \
154
154
  -d '{"username":"admin","password":"admin"}' \
155
155
  http://localhost:5151/nodefony/security/api/auth/login | head -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nodefony/security",
3
- "version": "10.0.0-alpha.5",
3
+ "version": "10.0.0-alpha.7",
4
4
  "description": "Pare-feu applicatif par zones pour Nodefony : authentification, autorisation par rôles, protection CSRF, journal d'audit",
5
5
  "author": "Christophe CAMENSULI <ccamensuli@gmail.com>",
6
6
  "main": "./dist/index.js",
@@ -44,29 +44,29 @@
44
44
  "directory": "src/packages/@nodefony/security"
45
45
  },
46
46
  "dependencies": {
47
- "@simplewebauthn/server": "14.0.1",
47
+ "@simplewebauthn/server": "14.0.2",
48
48
  "jose": "6.2.12",
49
49
  "tslib": "2.8.1",
50
- "zod": "^4.6.1"
50
+ "zod": "^4.6.5"
51
51
  },
52
52
  "devDependencies": {
53
- "@nodefony/framework": "^10.0.0-alpha.5",
54
- "@nodefony/http": "^10.0.0-alpha.5",
55
- "@nodefony/user": "^10.0.0-alpha.5",
56
- "@types/node": "26.5.1",
57
- "@vitest/coverage-v8": "5.0.0",
58
- "nodefony": "^10.0.0-alpha.5",
53
+ "@nodefony/framework": "^10.0.0-alpha.7",
54
+ "@nodefony/http": "^10.0.0-alpha.7",
55
+ "@nodefony/user": "^10.0.0-alpha.7",
56
+ "@types/node": "26.6.1",
57
+ "@vitest/coverage-v8": "5.0.1",
58
+ "nodefony": "^10.0.0-alpha.7",
59
59
  "rimraf": "6.1.3",
60
- "vitest": "5.0.0"
60
+ "vitest": "5.0.1"
61
61
  },
62
62
  "license": "Apache-2.0",
63
63
  "readmeFilename": "README.md",
64
64
  "contributors": [],
65
65
  "peerDependencies": {
66
- "@nodefony/framework": "^10.0.0-alpha.5",
67
- "@nodefony/http": "^10.0.0-alpha.5",
68
- "@nodefony/user": "^10.0.0-alpha.5",
69
- "nodefony": "^10.0.0-alpha.5"
66
+ "@nodefony/framework": "^10.0.0-alpha.7",
67
+ "@nodefony/http": "^10.0.0-alpha.7",
68
+ "@nodefony/user": "^10.0.0-alpha.7",
69
+ "nodefony": "^10.0.0-alpha.7"
70
70
  },
71
71
  "files": [
72
72
  "dist",