Generate, validate, and normalize rettX IDs for the Rett Syndrome Europe ecosystem
Project description
🧬 rettxid — RettX Patient Identifier Library
rettxid is the official Python library for generating and validating rettX IDs, the pseudonymous, GDPR-safe identifiers used across the rettX European Rett Syndrome Patient Registry.
A rettX ID is a stable, globally unique, non-PII, human-friendly identifier assigned to each patient record. It enables:
- safe cross-border data harmonization
- pseudonymous linking of datasets
- interoperability between registries, clinicians, and research groups
- QR-based emergency and verification workflows
- long-term governance for Rett Syndrome data in Europe
This repository contains the canonical reference implementation of the rettX ID format and generation rules.
Important: This library is stateless. It does not store rettX IDs or patient information.
Persistence and API endpoints are implemented in rettxapi.
✨ Features
- Pure Python implementation (Python 3.11+)
- Zero runtime dependencies (stdlib only)
- Cryptographically secure ID generation using
secretsmodule - Strict format validation with pre-compiled regex
- Input normalization (handles case variations, whitespace, missing dashes)
- Ambiguity-safe alphabet (excludes 0, 1, I, L, O, S)
- Full type annotations (PEP 561 compliant)
- 95%+ test coverage with property-based testing
- Designed for integration with rettxapi and other rettX services
📦 Installation
Once published to PyPI:
pip install rettxid
Or install directly from GitHub:
pip install git+https://github.com/rett-europe/rettxid.git
For development:
git clone https://github.com/rett-europe/rettxid.git
cd rettxid
python -m venv .venv
.venv\Scripts\activate # Windows
# source .venv/bin/activate # Linux/Mac
pip install -e ".[dev]"
🚀 Usage
Generate a New rettX ID
from rettxid import generate_rettx_id
# Generate a new cryptographically random rettX ID
rid = generate_rettx_id()
print(rid)
# → rettx-8GZ4-MK3P-2Q9A
Validate Format
from rettxid import validate_format
# Check if a string is a valid rettX ID format
validate_format("rettx-8GZ4-MK3P-2Q9A") # → True
validate_format("rettx-8gz4-mk3p-2q9a") # → False (lowercase body)
validate_format("invalid") # → False
validate_format(None) # → False (doesn't raise)
Normalize User Input
from rettxid import normalize
# Convert various input formats to canonical form
normalize("rettx-8gz4-mk3p-2q9a") # → "rettx-8GZ4-MK3P-2Q9A"
normalize("RETTX-8GZ4-MK3P-2Q9A") # → "rettx-8GZ4-MK3P-2Q9A"
normalize("rettx8GZ4MK3P2Q9A") # → "rettx-8GZ4-MK3P-2Q9A"
normalize(" rettx-8GZ4-MK3P-2Q9A ") # → "rettx-8GZ4-MK3P-2Q9A"
# Raises ValueError for invalid input
normalize("invalid") # → ValueError: Invalid rettX ID: 'invalid'
# Raises TypeError for non-string input
normalize(None) # → TypeError
📋 API Reference
generate_rettx_id() -> str
Generate a new cryptographically random rettX ID.
- Returns: A valid rettX ID in format
rettx-XXXX-XXXX-XXXX - Raises:
RuntimeErrorif system entropy is unavailable (rare)
validate_format(id: str) -> bool
Check if a string matches the rettX ID v1 format.
- Parameters:
id— The string to validate - Returns:
Trueif valid format,Falseotherwise - Note: Never raises; returns
Falsefor any invalid input including non-strings
normalize(id: str) -> str
Normalize a string into canonical rettX ID form.
- Parameters:
id— The string to normalize - Returns: The canonical rettX ID
- Raises:
ValueErrorif input cannot be normalizedTypeErrorif input is not a string
🔐 Format Specification
The rettX ID v1 format:
rettx-XXXX-XXXX-XXXX
- Prefix:
rettx-(6 characters, always lowercase) - Body: 3 groups of 4 characters, separated by dashes
- Alphabet: 30 ambiguity-safe characters:
23456789ABCDEFGHJKMNPQRTUVWXYZ - Excluded:
0(zero),1(one),I,L,O,S(visually confusable) - Total length: 20 characters
- Entropy: ~59 bits (collision probability < 1 in 30 million at 100K scale)
🔗 Integration with rettxapi
This library:
- Generates rettX IDs
- Validates rettX ID format
- Normalizes user input
The rettxapi backend:
- Stores
rettx_idinside patient documents - Ensures uniqueness
- Provides public & internal API endpoints
- Generates QR codes for rettX SOS
- Handles authentication, authorization, and audit logging
🧪 Testing
Run tests with:
pytest
Run with coverage:
pytest --cov=rettxid --cov-report=term-missing
Run type checking:
mypy src/rettxid --strict
Run linting:
ruff check src/rettxid tests
🗺️ Roadmap
- v1: ✅ Initial ID format definition and reference implementation
- v2: Optional checksum support
- v3: Backward-compatible decoding/format transitions
- Governance specification for rettX ID lifecycle
- Language bindings (Rust, TypeScript)
🤝 Contributing
Contributions are welcome! Please open an issue or PR.
📄 License
This project is licensed under the MIT License, a permissive open-source license ideal for libraries intended to be reused across registries, research tools, and backend services. See LICENSE for details.
❤️ About Rett Syndrome Europe
This project is maintained by Rett Syndrome Europe (RSE) as part of the rettX ecosystem — a pan-European effort to build harmonized, high-quality patient data infrastructure to support research, clinical care, and family empowerment.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file rettxid-1.0.0.tar.gz.
File metadata
- Download URL: rettxid-1.0.0.tar.gz
- Upload date:
- Size: 73.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1ea6248b932772a7098a97d79244cc7781d0aafffa6c71fc8e6d99d896985de6
|
|
| MD5 |
9df98bb0817c1632ebf0641059b763e4
|
|
| BLAKE2b-256 |
231cf94e324f386de7494bc4fa406463188c5ab69da8b93842da38a95f87ca8f
|
Provenance
The following attestation bundles were made for rettxid-1.0.0.tar.gz:
Publisher:
publish.yml on rett-europe/rettxid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rettxid-1.0.0.tar.gz -
Subject digest:
1ea6248b932772a7098a97d79244cc7781d0aafffa6c71fc8e6d99d896985de6 - Sigstore transparency entry: 747219486
- Sigstore integration time:
-
Permalink:
rett-europe/rettxid@ca51eee905b3c0c8f0ba7227cb5cdafefdba5d42 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/rett-europe
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca51eee905b3c0c8f0ba7227cb5cdafefdba5d42 -
Trigger Event:
release
-
Statement type:
File details
Details for the file rettxid-1.0.0-py3-none-any.whl.
File metadata
- Download URL: rettxid-1.0.0-py3-none-any.whl
- Upload date:
- Size: 10.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2b19fee8fbd6c8109ce439bf9e0cb2a5c9f6cba4bc5bc2ed38070b164cea3647
|
|
| MD5 |
f664ee7a174844ea2fc81313f2c28d68
|
|
| BLAKE2b-256 |
6a61cf443d301f0eba97e9140dd5553db8b0bfc937838fea252537fb46a769f1
|
Provenance
The following attestation bundles were made for rettxid-1.0.0-py3-none-any.whl:
Publisher:
publish.yml on rett-europe/rettxid
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
rettxid-1.0.0-py3-none-any.whl -
Subject digest:
2b19fee8fbd6c8109ce439bf9e0cb2a5c9f6cba4bc5bc2ed38070b164cea3647 - Sigstore transparency entry: 747219487
- Sigstore integration time:
-
Permalink:
rett-europe/rettxid@ca51eee905b3c0c8f0ba7227cb5cdafefdba5d42 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/rett-europe
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca51eee905b3c0c8f0ba7227cb5cdafefdba5d42 -
Trigger Event:
release
-
Statement type: