{
  "$schema": "../cases.schema.json",
  "format": 1,
  "domain": "cns",
  "title": {
    "en": "CNS (SUS card)",
    "pt-BR": "CNS (Cartão SUS)"
  },
  "functions": [
    {
      "id": "cns.format",
      "level": "extended",
      "summary": "Formats a CNS number into the common display groups of 3-4-4-4 digits separated by spaces.",
      "description": "Formats a CNS number into groups of 3-4-4-4 digits separated by spaces.\n\n- `options.pad` left-pads with zeros to 15 digits first.\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number returns an empty string (2.4.0 read the digits of any number, sign and decimal point dropped).\n- A value with no digits (empty, or only letters and symbols) returns an empty string, even with `pad`. Until 2.4.0 `pad` returned the full zero mask (`000 0000 0000 0000`) for it.\n- Digits after the 15th are dropped. Every non-digit character is ignored.",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        },
        {
          "name": "options",
          "type": "FormatCnsOptions",
          "optional": true
        }
      ],
      "returns": "string",
      "cases": [
        {
          "id": "cns.format#[\"123456789010001\"]",
          "args": [
            "123456789010001"
          ],
          "expect": {
            "returns": "123 4567 8901 0001"
          }
        },
        {
          "id": "cns.format#already-formatted",
          "args": [
            "898 0000 0004 3208"
          ],
          "expect": {
            "returns": "898 0000 0004 3208"
          }
        },
        {
          "id": "cns.format#partial",
          "args": [
            "1234"
          ],
          "expect": {
            "returns": "123 4"
          }
        },
        {
          "id": "cns.format#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": ""
          }
        },
        {
          "id": "cns.format#[\"1\"]",
          "args": [
            "1"
          ],
          "expect": {
            "returns": "1"
          },
          "note": "JavaScript's own test: should format a CNS with the 3-4-4-4 space mask"
        },
        {
          "id": "cns.format#[\"12\"]",
          "args": [
            "12"
          ],
          "expect": {
            "returns": "12"
          },
          "note": "JavaScript's own test: should format a CNS with the 3-4-4-4 space mask"
        },
        {
          "id": "cns.format#[\"123\"]",
          "args": [
            "123"
          ],
          "expect": {
            "returns": "123"
          },
          "note": "JavaScript's own test: should format a CNS with the 3-4-4-4 space mask"
        },
        {
          "id": "cns.format#[\"898000000043208\"]",
          "args": [
            "898000000043208"
          ],
          "expect": {
            "returns": "898 0000 0004 3208"
          },
          "note": "JavaScript's own test: should round trip 898 0000 0004 3208, the only concrete CNS the ANVISA page prints"
        },
        {
          "id": "cns.format#[123456789010001]",
          "args": [
            123456789010001
          ],
          "expect": {
            "returns": "123 4567 8901 0001"
          },
          "note": "JavaScript's own test: should format a number CNS with the space mask"
        },
        {
          "id": "cns.format#[\"\",{\"pad\":true}]",
          "args": [
            "",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": ""
          },
          "note": "changed in 2.5.0 (#615): a value with no digits gives an empty string even with pad. 2.4.0 returned 000 0000 0000 0000. JavaScript's own test: should return an empty string for a value without digits even when padding"
        },
        {
          "id": "cns.format#[\"89010001\",{\"pad\":true}]",
          "args": [
            "89010001",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": "000 0000 8901 0001"
          },
          "note": "JavaScript's own test: should pad the value with leading zeros when pad is true"
        },
        {
          "id": "cns.format#[\"123456789010001999\"]",
          "args": [
            "123456789010001999"
          ],
          "expect": {
            "returns": "123 4567 8901 0001"
          },
          "note": "JavaScript's own test: should not add digits after the CNS length (15)"
        },
        {
          "id": "cns.format#[\"123.456.789-01/0001\"]",
          "args": [
            "123.456.789-01/0001"
          ],
          "expect": {
            "returns": "123 4567 8901 0001"
          },
          "note": "JavaScript's own test: should remove all non numeric characters"
        },
        {
          "id": "cns.format#[-1]",
          "args": [
            -1
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cns.format#[1.5]",
          "args": [
            1.5
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cns.format#[9007199254740992]",
          "args": [
            9007199254740992
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cns.format#[\"abc\",{\"pad\":true}]",
          "args": [
            "abc",
            {
              "pad": true
            }
          ],
          "expect": {
            "returns": ""
          },
          "note": "a value with letters only has no digits"
        },
        {
          "id": "cns.format#[\"123456789010000\"]",
          "args": [
            "123456789010000"
          ],
          "expect": {
            "returns": "123 4567 8901 0000"
          },
          "note": "JavaScript docs example"
        },
        {
          "id": "cns.format#[123456789010000]",
          "args": [
            123456789010000
          ],
          "expect": {
            "returns": "123 4567 8901 0000"
          },
          "note": "JavaScript docs example"
        }
      ]
    },
    {
      "id": "cns.isValid",
      "level": "extended",
      "summary": "Validates a CNS number, the unique identifier of a SUS (Sistema Único de Saúde) user, health professional or health facility.",
      "description": "Validates a CNS number: 15 digits.\n\n- Definitive cards start with 1 or 2, provisional ones with 7, 8 or 9. Each kind has its own modulus 11 rule.\n- Definitive card (starts with 1 or 2): the first 11 digits are the base, then a 3-digit suffix (`000` or `001`), then the check digit. The check digit is 11 minus the remainder of the base's weighted sum by 11 (weights 15 down to 5), with 11 read as 0. When that result is 10, the sum is raised by 2, the digit is recomputed and the suffix is `001` instead of `000`.\n- Provisional card (starts with 7, 8 or 9): the weighted sum of all 15 digits (weights 15 down to 1) must be a multiple of 11.\n- Rejects a number that starts with 5, following ANVISA.\n- Accepts the bare digits or the printed 3-4-4-4 groups split by whitespace, `.`, `-` or `/`. Any run of those characters is accepted between two groups, and whitespace around the value is ignored; anything else (a letter, a separator inside a group or at the ends) is rejected.\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number is invalid.\n- No official source publishes the check digit rule as a norm. The rule follows the DATASUS \"Rotina de validação de CNS e Número Provisório\", published on the old Cartão Nacional de Saúde site (archived copy linked), and the ANVISA page. Neither names a first digit other than 1, 2, 7, 8 or 9, so a number starting with 5 is rejected even when its weighted sum checks out.\n- Docs examples: `100000000060018` (definitive, raw check digit 10, suffix 001) and `700000000000005` (provisional) are valid; `123456789010001` (wrong check digit) and `12345678901` (wrong length) are not.",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        }
      ],
      "returns": "boolean",
      "cases": [
        {
          "id": "cns.isValid#[\"123456789010000\"]",
          "args": [
            "123456789010000"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cns.isValid#masked",
          "args": [
            "123 4567 8901 0000"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cns.isValid#provisional",
          "args": [
            "898000000043208"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cns.isValid#starts-with-7",
          "args": [
            "700000000000005"
          ],
          "expect": {
            "returns": true
          }
        },
        {
          "id": "cns.isValid#wrong-check-digit",
          "args": [
            "123456789010001"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cns.isValid#invalid-first-digit",
          "args": [
            "312345678901234"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cns.isValid#too-short",
          "args": [
            "12345678901"
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cns.isValid#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": false
          }
        },
        {
          "id": "cns.isValid#[\"012345678901234\"]",
          "args": [
            "012345678901234"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the first digit is not 1, 2, 7, 8 or 9"
        },
        {
          "id": "cns.isValid#[\"612345678901234\"]",
          "args": [
            "612345678901234"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the first digit is not 1, 2, 7, 8 or 9"
        },
        {
          "id": "cns.isValid#[\"123456789010010\"]",
          "args": [
            "123456789010010"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a definitive card carries the 001 suffix without needing the +2 adjustment"
        },
        {
          "id": "cns.isValid#[\"100000000060000\"]",
          "args": [
            "100000000060000"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a definitive card whose raw check digit is 10 (base 10000000006) keeps the 000 suffix"
        },
        {
          "id": "cns.isValid#[\"100000000060008\"]",
          "args": [
            "100000000060008"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a definitive card whose raw check digit is 10 (base 10000000006) keeps the 000 suffix"
        },
        {
          "id": "cns.isValid#[\"700000000000001\"]",
          "args": [
            "700000000000001"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when a provisional card's weighted sum is not a multiple of 11"
        },
        {
          "id": "cns.isValid#[\"70000000000008\"]",
          "args": [
            "70000000000008"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it does not have 15 digits, even though a provisional-style weighted sum over the given digits would be a multiple of 11"
        },
        {
          "id": "cns.isValid#[\"012345678900006\"]",
          "args": [
            "012345678900006"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the first digit is not 1 or 2, even though a 1 or 2 appears later and the rest forms a valid definitive checksum"
        },
        {
          "id": "cns.isValid#[\"070000000000001\"]",
          "args": [
            "070000000000001"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the first digit is not 7, 8 or 9, even though one of them appears later and the rest forms a valid provisional checksum"
        },
        {
          "id": "cns.isValid#[\"abc123456789010000\"]",
          "args": [
            "abc123456789010000"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when letters are wrapped around the digits of a valid card"
        },
        {
          "id": "cns.isValid#[\"123456789010000abc\"]",
          "args": [
            "123456789010000abc"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when letters are wrapped around the digits of a valid card"
        },
        {
          "id": "cns.isValid#[\"1a2b3c456789010000\"]",
          "args": [
            "1a2b3c456789010000"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when letters are mixed in between the digits of a valid card"
        },
        {
          "id": "cns.isValid#[\"1234 5678 9010 000\"]",
          "args": [
            "1234 5678 9010 000"
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when the 15 digits are grouped outside the printed 3-4-4-4 mask"
        },
        {
          "id": "cns.isValid#[\"200000000010009\"]",
          "args": [
            "200000000010009"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS starting with 2 (base 20000000001, weighted sum 35, digit 9)"
        },
        {
          "id": "cns.isValid#[123456789010000]",
          "args": [
            123456789010000
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS as a number"
        },
        {
          "id": "cns.isValid#[\"123.4567.8901.0000\"]",
          "args": [
            "123.4567.8901.0000"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS with a dotted mask"
        },
        {
          "id": "cns.isValid#[\"123-4567-8901-0000\"]",
          "args": [
            "123-4567-8901-0000"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS split by the other interchangeable separators"
        },
        {
          "id": "cns.isValid#[\"123/4567/8901/0000\"]",
          "args": [
            "123/4567/8901/0000"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS split by the other interchangeable separators"
        },
        {
          "id": "cns.isValid#[\"123.4567-8901/0000\"]",
          "args": [
            "123.4567-8901/0000"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS split by the other interchangeable separators"
        },
        {
          "id": "cns.isValid#[\"123 - 4567 8901 0000\"]",
          "args": [
            "123 - 4567 8901 0000"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS split by the other interchangeable separators"
        },
        {
          "id": "cns.isValid#[\" 123456789010000 \"]",
          "args": [
            " 123456789010000 "
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS with leading and trailing whitespace"
        },
        {
          "id": "cns.isValid#[\"100000000060018\"]",
          "args": [
            "100000000060018"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a definitive CNS whose raw check digit is 10 (base 10000000006, weighted sum 45): sum raised to 47, digit 8, suffix 001"
        },
        {
          "id": "cns.isValid#[\"800000000000001\"]",
          "args": [
            "800000000000001"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a provisional CNS starting with 8"
        },
        {
          "id": "cns.isValid#[\"898 0000 0004 3208\"]",
          "args": [
            "898 0000 0004 3208"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for 898 0000 0004 3208, the only concrete CNS the ANVISA page prints (weighted sum 396)"
        },
        {
          "id": "cns.isValid#[\"900000000000008\"]",
          "args": [
            "900000000000008"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a provisional CNS starting with 9"
        },
        {
          "id": "cns.isValid#[\"712345678901236\"]",
          "args": [
            "712345678901236"
          ],
          "expect": {
            "returns": true
          },
          "note": "JavaScript's own test: should return true for a provisional CNS whose base 11 digits would NOT be a valid definitive checksum"
        },
        {
          "id": "cns.isValid#[-139457218230006]",
          "args": [
            -139457218230006
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it is a negative or fractional number (#593 number rule)"
        },
        {
          "id": "cns.isValid#[13945721823.0006]",
          "args": [
            13945721823.0006
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript's own test: should return false when it is a negative or fractional number (#593 number rule)"
        },
        {
          "id": "cns.isValid#[-123456789010000]",
          "args": [
            -123456789010000
          ],
          "expect": {
            "returns": false
          },
          "note": "JavaScript docs example (not a non-negative safe integer)"
        }
      ]
    },
    {
      "id": "cns.parse",
      "level": "extended",
      "summary": "Removes the formatting characters of a CNS number and returns only the digits.",
      "description": "Removes CNS formatting and keeps only digits, capped at 15 digits.\n\n- A number is read only when it is a safe non-negative integer. A negative, fractional, non-finite or unsafe number returns an empty string (2.4.0 read the digits of any number, sign and decimal point dropped).",
      "params": [
        {
          "name": "value",
          "type": "string | number"
        }
      ],
      "returns": "string",
      "cases": [
        {
          "id": "cns.parse#masked",
          "args": [
            "123 4567 8901 0000"
          ],
          "expect": {
            "returns": "123456789010000"
          }
        },
        {
          "id": "cns.parse#unmasked",
          "args": [
            "123456789010000"
          ],
          "expect": {
            "returns": "123456789010000"
          }
        },
        {
          "id": "cns.parse#strips-non-digits",
          "args": [
            "123.?ABC4567 8901-0000abc"
          ],
          "expect": {
            "returns": "123456789010000"
          }
        },
        {
          "id": "cns.parse#empty",
          "args": [
            ""
          ],
          "expect": {
            "returns": ""
          }
        },
        {
          "id": "cns.parse#caps-length",
          "args": [
            "123456789010000999"
          ],
          "expect": {
            "returns": "123456789010000"
          },
          "note": "reference truncates to the 15 characters of the document; asserted by the reference (JS) unit tests"
        },
        {
          "id": "cns.parse#[123456789010000]",
          "args": [
            123456789010000
          ],
          "expect": {
            "returns": "123456789010000"
          },
          "note": "JavaScript's own test: should read a number as the string of its digits"
        },
        {
          "id": "cns.parse#[-1]",
          "args": [
            -1
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cns.parse#[1.5]",
          "args": [
            1.5
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        },
        {
          "id": "cns.parse#[9007199254740992]",
          "args": [
            9007199254740992
          ],
          "expect": {
            "returns": ""
          },
          "note": "JavaScript's own test: should return an empty string when it is a negative, fractional or unsafe number (#593 number rule)"
        }
      ]
    }
  ]
}
