Metadata-Version: 2.4
Name: hardguard25
Version: 1.3.8
Summary: HardGuard25: A 25-character low-confusion alphabet for human-readable identifiers.
Author-email: Snap Synapse <info@snapsynapse.com>
License-Expression: MIT
Project-URL: Homepage, https://hardguard25.com/
Project-URL: Documentation, https://hardguard25.com/
Project-URL: Specification, https://github.com/snapsynapse/hardguard25/blob/main/SPEC.md
Project-URL: Repository, https://github.com/snapsynapse/hardguard25
Project-URL: Changelog, https://github.com/snapsynapse/hardguard25/blob/main/CHANGELOG.md
Project-URL: Issues, https://github.com/snapsynapse/hardguard25/issues
Project-URL: Security, https://github.com/snapsynapse/hardguard25/security/policy
Project-URL: Funding, https://github.com/sponsors/snapsynapse
Keywords: id,uid,unique-id,identifier,human-readable,unambiguous
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: license-file

# hardguard25

Python reference implementation of **HardGuard25** — an open standard for human-safe identifiers.

```
0 1 2 3 4 5 6 7 8 9 A C D F G H J K M N P R U W Y
```

HardGuard25 is a 25-character alphabet designed to exclude common visual confusables, including patterns relevant to dyslexia-sensitive workflows. It removes 11 letters associated with predictable confusion (`I L O B S Z E T V X Q`). When a letter and a digit compete for the same visual slot, the digit always wins. Comparative OCR and transcription error rates have not yet been established empirically.

## Install

```bash
pip install hardguard25
```

Requires Python 3.9+.

## Quickstart

```python
from hardguard25 import generate, validate, normalize, check_digit, verify_check_digit

generate(8)                       # e.g. "AC3H7PUW"
generate(8, check_digit=True)     # e.g. "AC3H7PUWN"  (length+1)

validate("ac3h-7puw")             # True  (case and separators tolerated)
normalize("ac3h-7puw")            # "AC3H7PUW"

check_digit("AC3H7PUW")           # "N"
verify_check_digit("AC3H7PUWN")   # True
```

Normalization removes the Unicode White_Space set pinned by the specification plus `-`, `_`, and `.`, and rejects empty or separator-only input. Validation returns `False` for invalid input, and check-digit calculation rejects an empty payload.

## API

| Function | Purpose |
|---|---|
| `generate(length, *, check_digit=False)` | Cryptographically secure random ID using rejection sampling for uniform distribution |
| `validate(s)` | `True` if `s` normalizes to a valid HardGuard25 ID; never raises |
| `normalize(s)` | Remove pinned Unicode White_Space and `-` `_` `.`, uppercase, and reject other characters |
| `check_digit(code)` | Mod-25 weighted check digit for manual-entry error detection |
| `verify_check_digit(code)` | Strip last char, recompute, compare |
| `ALPHABET` | `"0123456789ACDFGHJKMNPRUWY"` |

Type hints and `py.typed` marker included.

## Sizing

Each character carries `log2(25) = 4.64` bits of entropy.

| Length | Bits | Possible Strings | Typical Use |
|-------:|-----:|-----------:|-------------|
| 4 | 18.6 | 390,625 | Small inventory, tickets |
| 5 | 23.2 | 9,765,625 | Small business |
| 6 | 27.9 | 244,140,625 | Medium businesses |
| 7 | 32.5 | 6.1 billion | Large catalogs |
| 8 | 37.2 | 152.6 billion | Large systems |
| 12 | 55.7 | 5.96 × 10¹⁶ | Internal tokens |
| 16 | 74.3 | 2.33 × 10²² | Cross-system IDs |
| 20 | 92.9 | 9.09 × 10²⁷ | Public tokens |
| 22 | 102.2 | 5.68 × 10³⁰ | Internet-scale |

These values are possible payload strings, not safe random issuance counts. Random issuance must account for birthday collisions. An appended check digit is derived from the payload and does not add random entropy.

Recommended defaults:

- 16 for internal systems up to millions of IDs
- 20 for public tokens or cross-org use
- 22 for long-lived, internet-scale identifiers

See the [spec](https://github.com/snapsynapse/hardguard25/blob/main/SPEC.md) for collision-bound tables.

## Implementation guidance

For project integration guidance, see:
- Human implementation guide: https://github.com/snapsynapse/hardguard25/blob/main/docs/IMPLEMENTATION.md
- Assistant guide: https://hardguard25.com/.well-known/assistant-guide.txt
- Assistant guide SHA-256: https://hardguard25.com/.well-known/assistant-guide.txt.sha256

## When NOT to Use HardGuard25

- Cryptographic keys (use proper key derivation)
- Blockchain consensus (use domain-specific formats)
- Systems requiring global UUID guarantees (use UUIDv7 or ULID)
- Machine-only contexts where no human ever sees the ID

## Reference

- Spec: https://github.com/snapsynapse/hardguard25/blob/main/SPEC.md
- Homepage: https://hardguard25.com/
- Source: https://github.com/snapsynapse/hardguard25
- Other languages: JavaScript, Go (same repo)

## License

MIT
