Scope-bound opaque id masking for integers, strings, and UUIDs.
Project description
ScopeMask (Python)
ScopeMask converts internal identifiers: database keys, emails, UUIDs, etc into short, opaque strings that are safe to expose in URLs and APIs, and decodes them back to the original value on demand. Each id is bound to a scope and a secret, with a keyed integrity check.
Install
pip install scopemask
# or
uv add scopemask
Configuration
Create a ScopeMask with a secret. The secret is required and is the key every id is derived from; keep it private and stable.
from scopemask import ScopeMask
scope_mask = ScopeMask("parity-secret")
Optional keyword arguments:
min_length: pad every id to at least this many characters (default 16).base_alphabet: the characters ids are built from; must be unique (default A–Z, a–z, 0–9).previous_secrets: extra secrets accepted when decoding but never used for encoding, so ids made with an old secret keep working after you rotate.
scope_mask = ScopeMask(
"parity-secret",
min_length=24,
base_alphabet="ABCDEFGHJKLMNPQRSTUVWXYZ23456789",
previous_secrets=("old-secret",),
)
Encode and decode
scope_mask.encode("user", 42) # "xgFeePgoWUZHCNLo"
scope_mask.decode("user", "xgFeePgoWUZHCNLo") # 42
Value types
Integers, strings, bytes, and UUIDs are supported. The original type is restored on decode.
import uuid
scope_mask.encode("user", "hello") # "yqBiRnZBIdqXslkrXM"
scope_mask.encode("user", b"\x00\x01\xff") # "RLDIyRQmFljZ1gBD"
scope_mask.encode("user", uuid.UUID("12345678-1234-5678-1234-567812345678"))
# "miQAnixf6TYaACwhThxDJ973X5vSuKqjp2W"
Scopes
The same value produces a different id in each scope.
scope_mask.encode("user", 42) # "xgFeePgoWUZHCNLo"
scope_mask.encode("order", 42) # "8DGttE8msCZHsJVG"
Prefixes
Add a prefix for readable ids. Pass the same prefix when decoding.
scope_mask.encode("user", 42, prefix="id_") # "id_xgFeePgoWUZHCNLo"
scope_mask.encode("webhook", 42, prefix="whs_") # "whs_jU5IIH0OxGnQg5u1"
scope_mask.decode("user", "id_xgFeePgoWUZHCNLo", prefix="id_") # 42
Bound scope
Bind a scope and prefix once, then call the same methods without repeating them.
users = scope_mask.scope("user", prefix="id_")
users.encode(42) # "id_xgFeePgoWUZHCNLo"
users.decode("id_xgFeePgoWUZHCNLo") # 42
users.try_decode("not-a-real-id") # None
ids = users.encode_many([1, 2, 3])
users.decode_many(ids) # [1, 2, 3]
users.try_decode_many(ids) # [1, 2, 3]
Batch operations
ids = scope_mask.encode_many("user", [1, 2, 3])
scope_mask.decode_many("user", ids) # [1, 2, 3]
Safe decoding
decode raises InvalidId on an invalid id. Use try_decode to get None instead.
scope_mask.try_decode("user", "not-a-real-id") # None
scope_mask.try_decode_many("user", ["not-a-real-id"]) # [None]
scope_mask.encode("user", None) # None
Additional resources
See Overview for more details.
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 scopemask-1.0.0.tar.gz.
File metadata
- Download URL: scopemask-1.0.0.tar.gz
- Upload date:
- Size: 66.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1298f6aee4b6e459ab9ef49459c966ccd60569d25f7643e34442d441e0cbe372
|
|
| MD5 |
6e692301d4c2acfb9916e6f32f4ef365
|
|
| BLAKE2b-256 |
098046df25d2b32026c99df3e5c9554f36da6d63babd34a0daa49345716e9d39
|
Provenance
The following attestation bundles were made for scopemask-1.0.0.tar.gz:
Publisher:
publish-python.yml on khan-asfi-reza/scopemask
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scopemask-1.0.0.tar.gz -
Subject digest:
1298f6aee4b6e459ab9ef49459c966ccd60569d25f7643e34442d441e0cbe372 - Sigstore transparency entry: 1740490970
- Sigstore integration time:
-
Permalink:
khan-asfi-reza/scopemask@68d99ca5b3eaf76b4a1204bb4336d260c8584952 -
Branch / Tag:
refs/tags/py/v1.0.0 - Owner: https://github.com/khan-asfi-reza
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@68d99ca5b3eaf76b4a1204bb4336d260c8584952 -
Trigger Event:
release
-
Statement type:
File details
Details for the file scopemask-1.0.0-py3-none-any.whl.
File metadata
- Download URL: scopemask-1.0.0-py3-none-any.whl
- Upload date:
- Size: 6.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4d02159434feb4588e56dc118b1b9684b1a33bbef3aae8de1c6750cec674315
|
|
| MD5 |
5cf3b778e48b2cdb406f264223a7fe75
|
|
| BLAKE2b-256 |
8a903a7e1bd49e1c5965a6cd394cd2e2558bdc7763d99f97f30b34b03292817a
|
Provenance
The following attestation bundles were made for scopemask-1.0.0-py3-none-any.whl:
Publisher:
publish-python.yml on khan-asfi-reza/scopemask
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
scopemask-1.0.0-py3-none-any.whl -
Subject digest:
a4d02159434feb4588e56dc118b1b9684b1a33bbef3aae8de1c6750cec674315 - Sigstore transparency entry: 1740490975
- Sigstore integration time:
-
Permalink:
khan-asfi-reza/scopemask@68d99ca5b3eaf76b4a1204bb4336d260c8584952 -
Branch / Tag:
refs/tags/py/v1.0.0 - Owner: https://github.com/khan-asfi-reza
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-python.yml@68d99ca5b3eaf76b4a1204bb4336d260c8584952 -
Trigger Event:
release
-
Statement type: