Metadata-Version: 2.5
Name: privmask
Version: 0.1.0
Summary: Production-ready local-first privacy detection, masking, and de-identification engine
Project-URL: Homepage, https://github.com/toshakparmar/privmask
Project-URL: Documentation, https://toshakparmar.github.io/privmask
Project-URL: Repository, https://github.com/toshakparmar/privmask.git
Project-URL: Issues, https://github.com/toshakparmar/privmask/issues
Project-URL: Changelog, https://github.com/toshakparmar/privmask/blob/main/CHANGELOG.md
Author-email: Toshak Parmar <toshakparmar@privmask.dev>
Maintainer-email: Toshak Parmar <toshakparmar@privmask.dev>
License: Apache-2.0
License-File: LICENSE
Keywords: compliance,de-identification,gdpr,hipaa,masking,pii,privacy,redaction,security,tokenization
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.11
Provides-Extra: all
Requires-Dist: build>=1.1.0; extra == 'all'
Requires-Dist: hypothesis>=6.98.0; extra == 'all'
Requires-Dist: mkdocs-material>=9.5.0; extra == 'all'
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'all'
Requires-Dist: mypy>=1.9.0; extra == 'all'
Requires-Dist: pytest-cov>=4.1.0; extra == 'all'
Requires-Dist: pytest>=8.0.0; extra == 'all'
Requires-Dist: pyyaml>=6.0.1; extra == 'all'
Requires-Dist: ruff>=0.4.0; extra == 'all'
Requires-Dist: twine>=5.0.0; extra == 'all'
Provides-Extra: dev
Requires-Dist: build>=1.1.0; extra == 'dev'
Requires-Dist: hypothesis>=6.98.0; extra == 'dev'
Requires-Dist: mypy>=1.9.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: ruff>=0.4.0; extra == 'dev'
Requires-Dist: twine>=5.0.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-material>=9.5.0; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24.0; extra == 'docs'
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0.1; extra == 'yaml'
Description-Content-Type: text/markdown

# PrivMask

[![PyPI version](https://badge.fury.io/py/privmask.svg)](https://pypi.org/project/privmask/)
[![PyPI - Downloads](https://img.shields.io/pypi/dm/privmask?color=blue&label=PyPI%20Downloads)](https://pypi.org/project/privmask/)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/privmask)](https://pypi.org/project/privmask/)
[![CI](https://github.com/toshakparmar/privmask/actions/workflows/tests.yml/badge.svg)](https://github.com/toshakparmar/privmask/actions)
[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](LICENSE)
[![Security: Zero-Leakage](https://img.shields.io/badge/security-zero--leakage-brightgreen.svg)](SECURITY.md)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
[![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://toshakparmar.github.io/privmask)

**PrivMask** is a production-grade, local-first privacy detection, masking, and de-identification library for Python.

It enables developers to identify sensitive information (PII, credentials, API keys, tokens, secrets) in unstructured text and structured formats (JSON, CSV) and transform it deterministically according to explicit policies.

---

## Key Features

- **100% Local-First & Zero Network Calls**: Runs entirely on your hardware. No cloud services, external APIs, telemetry, or remote dependencies.
- **Zero-Leakage Architecture**: Secrets and PII are protected at every level. Sensitive substrings are never rendered in `repr()`, `str()`, exception traces, log formatters, or serialized statistics.
- **Single-Pass Slice Transformation**: $O(N)$ linear-time slice reconstruction instead of quadratic, collision-prone string replacements.
- **Deterministic Overlap Resolution**: Resolves overlapping entities (e.g. URLs vs emails) based on priority weights, span length, confidence, and stable tie-breaking.
- **Structured Data Awareness**: Deep recursive JSON traversal and CSV stream processing with field-name and column-specific transformation rules.
- **Modular & Extensible**: Pluggable `Detector`, `Transformer`, `Processor`, and `TokenStore` interfaces.
- **Cryptographically Sound**: Modern SHA-256 and HMAC-SHA256 hashing with salt support; strictly forbids insecure algorithms like MD5 and SHA-1.
- **Zero Heavy Dependencies in Core**: Pure standard library implementation with zero mandatory runtime dependencies.

---

## Installation

```bash
pip install privmask
```

Optional extras:
```bash
pip install privmask[yaml]  # YAML policy configuration support
pip install privmask[all]   # Full development & YAML suite
```

---

## Quickstart

### 1. Basic Text Masking

```python
import privmask

text = "Contact Alice at alice@example.com or call +1-800-555-0199."
safe_text = privmask.mask(text)

print(safe_text)
# Output: Contact Alice at [EMAIL] or call [PHONE].
```

### 2. Scanning without Modifying

```python
import privmask

report = privmask.scan("Server key: AKIAIOSFODNN7EXAMPLE")
print(f"Findings detected: {len(report.findings)}")
for finding in report.findings:
    print(
        f" - {finding.entity_type} [{finding.start}:{finding.end}] (confidence: {finding.confidence})"
    )
```

### 3. Custom Policy & Strategies

```python
from privmask import PrivacyMask, Policy, Rule, Strategy

policy = Policy(
    default_strategy=Strategy.MASK,
    rules={
        "EMAIL": Rule(strategy=Strategy.HASH, options={"length": 12}),
        "PHONE": Rule(
            strategy=Strategy.PARTIAL, options={"visible_prefix": 3, "visible_suffix": 4}
        ),
        "API_KEY": Rule(strategy=Strategy.REDACT),
    },
)

pm = PrivacyMask(policy=policy)
result = pm.mask(
    "User john@company.com (Phone: +91-9876543210, Key: ghp_1234567890abcdefghijklmnopqrstuvwxyz12)"
)
print(result.output)
```

### 4. Structured JSON Processing

```python
from privmask import PrivacyMask, Policy, Rule, Strategy

policy = Policy(
    default_strategy=Strategy.MASK,
    field_rules={
        "password": Rule(strategy=Strategy.REDACT),
        "phone": Rule(strategy=Strategy.PARTIAL),
    },
)

pm = PrivacyMask(policy=policy)
data = {
    "user": {
        "email": "customer@example.com",
        "phone": "9876543210",
        "password": "SecretPassword123!",
    }
}

result = pm.mask(data)
print(result.output)
# Output:
# {
#   "user": {
#     "email": "[EMAIL]",
#     "phone": "98******10",
#     "password": "[REDACTED]"
#   }
# }
```

### 5. Safe Logging Integration

```python
import logging
from privmask import wrap_logger

logger = logging.getLogger("my_app")
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())

# Wrap logger to automatically mask sensitive data before emission
wrap_logger(logger)

logger.info("User registered with email %s", "alice@example.com")
# Output: User registered with email [EMAIL]
```

---

## CLI Usage

```bash
# Check version
privmask version

# List active detectors
privmask detectors

# Scan a file
privmask scan app.log

# Scan via STDIN with JSON output
cat app.log | privmask scan --stdin --format json

# Mask a file to an output destination
privmask mask input.txt -o sanitized.txt

# Apply a custom YAML policy
privmask mask input.json -c policy.yaml
```

---

## Built-in Detectors

| Detector | Entity Types | Description | Priority |
| :--- | :--- | :--- | :--- |
| `email` | `EMAIL` | RFC-compatible email address detection | 70 |
| `phone` | `PHONE` | International, US, UK, and Indian mobile numbers | 60 |
| `credit_card` | `CREDIT_CARD` | Visa, Mastercard, Amex, Discover with Luhn validation | 80 |
| `api_key` | `API_KEY` | AWS, GitHub, Stripe, Google, Slack, and AI tokens | 85 |
| `jwt` | `JWT` | 3-part base64url encoded JSON Web Tokens | 85 |
| `ip` | `IPV4`, `IPV6`, `IP_ADDRESS` | Validated IP addresses via `ipaddress` | 65 |
| `url` | `URL` | HTTP, HTTPS, and FTP web URLs | 55 |
| `secret` | `SECRET` | High-entropy secrets and Bearer authorization tokens | 75 |

---

## Built-in Transformers

- **`mask`**: Entity-aware tokens (`[EMAIL]`, `[PHONE]`) or character masking (`******`).
- **`redact`**: Fixed redaction markers (`[REDACTED]`, `[PRIVATE]`).
- **`replace`**: Static user-specified replacement strings.
- **`hash`**: Cryptographic SHA-256 / HMAC-SHA256 with optional salt and truncation.
- **`partial`**: Context-preserving masking (e.g. `j***@example.com`, `+91-******3210`).
- **`tokenize`**: Consistent pseudonyms with thread-safe session stores (`<EMAIL_001>`).

---

## Security Policy

Please review [SECURITY.md](SECURITY.md) for detailed information on our threat model, zero-leakage guarantees, and vulnerability reporting procedures.

---

## Contributing

Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for development environment setup, coding guidelines, and quality standards.

---

## License

PrivMask is licensed under the Apache License, Version 2.0. See [LICENSE](LICENSE) for details.
