{
  "ruleId": "S051",
  "name": "Support 12–64 char passwords; reject >128",
  "description": "Enforce modern password length policy (min 12, typical max 64; reject >128) and align FE/BE validators. Warn on bcrypt 72-byte truncation.",
  "category": "security",
  "severity": "error",
  "options": {
    "lengthPolicy": {
      "minAllowedRange": {
        "min": 8,
        "recommended": 12,
        "warnBelow": 12,
        "errorBelow": 8
      },
      "maxRecommended": 64,
      "hardRejectLength": 128
    },
    "mode": "strict",
    "passwordIdentifiers": [
      "password", "newPassword", "oldPassword", "confirmPassword", 
      "passwd", "pwd", "passphrase", "secret", "credential"
    ],
    "uiHints": [
      "type=[\"']password[\"']",
      "placeholder.*password",
      "label.*password",
      "i18n.*password"
    ],
    "contextSignals": {
      "routes": ["auth", "signup", "register", "login", "reset", "change-password"],
      "files": ["auth", "password", "credential", "security"],
      "methods": ["hashPassword", "validatePassword", "checkPassword"]
    },
    "validatorPatterns": {
      "fe": [
        "minLength\\s*:\\s*(\\d+)",
        "maxLength\\s*:\\s*(\\d+)", 
        "yup\\.string\\(\\).*\\.min\\((\\d+)\\).*\\.max\\((\\d+)\\)",
        "z\\.string\\(\\).*\\.min\\((\\d+)\\).*\\.max\\((\\d+)\\)",
        "Validators\\.minLength\\((\\d+)\\)",
        "Validators\\.maxLength\\((\\d+)\\)",
        "minlength=[\"']?(\\d+)[\"']?",
        "maxlength=[\"']?(\\d+)[\"']?"
      ],
      "be": [
        "Joi\\.string\\(\\).*min\\((\\d+)\\).*max\\((\\d+)\\)",
        "Length\\s*\\(\\s*min\\s*=\\s*(\\d+).*max\\s*=\\s*(\\d+)\\)",
        "@Size\\s*\\(\\s*min\\s*=\\s*(\\d+).*max\\s*=\\s*(\\d+)\\)",
        "if\\s*\\(.*password\\.length\\s*[<>]=?\\s*(\\d+)\\)"
      ]
    },
    "bcryptHints": {
      "apis": [
        "bcrypt\\.", "BCrypt\\.", "bcryptjs", "@nestjs/bcrypt",
        "org\\.springframework\\.security\\.crypto\\.bcrypt"
      ],
      "warnOnMissingLengthCheck": true,
      "byteLimit": 72,
      "checkMethods": ["hash", "hashSync", "compare", "compareSync"]
    },
    "crossFileAnalysis": {
      "enabled": true,
      "compareFeBeMinMax": true,
      "warnOnMismatch": true,
      "toleranceDiff": 2
    },
    "policy": {
      "requireMinSignals": 2,
      "alignFeBe": true,
      "rejectOverHardLimit": true,
      "priorityOrder": ["weak_validators", "bcrypt_issues", "hard_limit"]
    },
    "allowlist": {
      "paths": ["test/", "tests/", "__tests__/", "fixtures/", "mocks/", "dummy/"],
      "notes": "Test and dummy files may have different password requirements"
    },
    "thresholds": {
      "maxWeakValidators": 0,
      "maxBcryptWithoutLengthCheck": 0,
      "maxMissingHardLimit": 1
    }
  }
}