🔐 TitanVault
The Secure, Lightweight, and Type-Safe Local Storage for the Future
TitanVault is a Python library for local-first encrypted data storage. It gives you an ORM-like API backed by SQLite, where every record is transparently encrypted with AES-256-GCM before it ever touches disk. No configuration required.
✨ Features
| Feature | Detail |
|---|---|
| Type-Safe API | Define schemas with plain Python type annotations — full IDE auto-complete |
| AES-256-GCM Encryption | Authenticated encryption at rest — every record, always |
| PBKDF2 Key Derivation | 600,000 iterations (NIST 2023 recommendation) |
| Zero-Config SQLite | Tables are created and migrated automatically |
| Atomic Transactions | ACID-compliant writes via save_many() and vault.transaction() |
| Fluent Query Builder | .filter(), .order_by(), .limit(), .first(), .count() |
| Minimal Dependencies | Only cryptography (the gold-standard Python crypto library) |
📦 Installation
pip install titanvault
Requirements: Python 3.10+, cryptography>=41.0.0
🚀 Quick Start
from titanvault import Vault, TitanModel
# 1. Define your schema — just type annotations, no boilerplate
class SecretKey(TitanModel):
service: str
username: str
password: str
# 2. Open (or create) an encrypted vault
vault = Vault("my_vault.db", secret_key="super-secret-password")
# 3. Save a record — encrypted automatically
new_key = SecretKey(service="Github", username="titan", password="gh_abc123")
vault.save(new_key)
print(new_key._id) # Auto-generated UUID: "a1b2c3d4-..."
# 4. Query — decrypted and returned as a typed object
result = vault.query(SecretKey).filter(service="Github").first()
print(result.username) # titan (with full IDE auto-complete)
print(result.password) # gh_abc123
vault.close()
📖 Usage Guide
Defining Models
from titanvault import TitanModel
class ApiCredential(TitanModel):
provider: str
api_key: str
is_active: bool = True
rate_limit: int = 1000
class UserNote(TitanModel):
title: str
body: str
category: str = "general"
Every subclass of TitanModel is automatically a @dataclass. The following metadata fields are managed by the Vault:
| Field | Type | Description |
|---|---|---|
_id |
str |
UUID v4 primary key |
_created_at |
str |
ISO-8601 UTC timestamp of first save |
_updated_at |
str |
ISO-8601 UTC timestamp of last save |
Opening a Vault
# Option A: Manual lifecycle
vault = Vault("path/to/vault.db", secret_key="my-password")
# ... use vault ...
vault.close()
# Option B: Context manager (recommended)
with Vault("path/to/vault.db", secret_key="my-password") as vault:
# ... use vault ...
Saving Records
# Single record
key = ApiCredential(provider="OpenAI", api_key="sk-...")
vault.save(key)
print(key._id) # UUID assigned after save
# Update (pass the same record again)
key.api_key = "sk-new-key"
vault.save(key) # upsert — _created_at preserved, _updated_at refreshed
# Bulk save (atomic — all succeed or all fail)
records = [
ApiCredential(provider=f"Service{i}", api_key=f"key-{i}")
for i in range(100)
]
vault.save_many(records)
Querying Records
# Get all records of a type
all_keys = vault.query(ApiCredential).all()
# Filter by one or more fields
active_keys = vault.query(ApiCredential).filter(is_active=True).all()
# Get the first match
openai_key = vault.query(ApiCredential).filter(provider="OpenAI").first()
# Check existence
exists = vault.query(ApiCredential).filter(provider="OpenAI").exists()
# Count
total = vault.query(ApiCredential).count()
# Order by a field
sorted_keys = vault.query(ApiCredential).order_by("provider").all()
sorted_desc = vault.query(ApiCredential).order_by("provider", desc=True).all()
# Pagination
page = vault.query(ApiCredential).order_by("provider").offset(10).limit(10).all()
# Get by UUID
record = vault.get(ApiCredential, "a1b2c3d4-...")
# Total count (fast — no decryption)
n = vault.count(ApiCredential)
Deleting Records
# Delete a record object
vault.delete(key)
# Delete by UUID
vault.delete_by_id(ApiCredential, "a1b2c3d4-...")
# Drop an entire collection (⚠️ irreversible)
vault.drop_collection(ApiCredential)
Atomic Transactions
# Explicit transaction block
with vault.transaction():
vault.save(record_a)
vault.save(record_b)
vault.delete(old_record)
# All committed on block exit, rolled back on any exception
🔒 Security Architecture
User Password
│
▼
PBKDF2-HMAC-SHA256 (600,000 iterations + 32-byte random salt)
│
▼
AES-256 Key
│
├── For each save():
│ JSON(record) ──► AES-256-GCM(nonce=random 12B) ──► BLOB on disk
│
└── For each read():
BLOB on disk ──► AES-256-GCM decrypt ──► JSON ──► Python object
Key properties:
- Confidentiality: AES-256 (256-bit key) — computationally infeasible to brute-force
- Integrity: GCM authentication tag — any tampering raises
DecryptionError - Freshness: New random nonce per record — same plaintext produces different ciphertext
- Password hardening: PBKDF2 with 600K iterations slows brute-force password attacks
- Zero plaintext on disk: Field values are never stored unencrypted
⚙️ Schema Evolution (Auto-Migration)
Adding new optional fields with defaults to an existing model "just works":
# Version 1 (data already saved)
class SecretKey(TitanModel):
service: str
password: str
# Version 2 (add a new optional field — old records use the default)
class SecretKey(TitanModel):
service: str
password: str
notes: str = "" # ← new field; old records will read "" automatically
tags: str = "[]" # ← another new field
🧪 Running Tests
pip install -e ".[dev]"
pytest
pytest --cov=titanvault --cov-report=term-missing # with coverage
🗺️ Roadmap
- Encrypted Blob Storage (large file support)
- End-to-End Encrypted Cloud Sync
- Argon2id key derivation (memory-hard, stronger than PBKDF2)
- Quantum-Resistant Key Exchange (CRYSTALS-Kyber)
- Async (asyncio) API
� Credits
Created and maintained by: Phenphet-k
�📄 License
MIT License — see LICENSE for details.
Metadata
Release files for titanvault 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| titanvault-1.0.0.tar.gz | 39.5 kB | Without provenance | Details for titanvault-1.0.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| titanvault-1.0.0-py3-none-any.whl | Python 3 | none | any | Details for titanvault-1.0.0-py3-none-any.whl |
Total release size: 58.0 kB
Release files / titanvault-1.0.0.tar.gz
| Download URL | titanvault-1.0.0.tar.gz |
|---|---|
| Size | 39.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0159005060fe11c36cca3d5c14eef0e3f1881edaeddcc31487acc166184965e3
|
|
BLAKE2b-256 checksum How to use checksums |
f59d8e342f4f19a131d8a7d413461953ee142459385e643704bb50251680b18d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Release files / titanvault-1.0.0-py3-none-any.whl
| Download URL | titanvault-1.0.0-py3-none-any.whl |
|---|---|
| Size | 18.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4323a1e99695a7b027d69bca5954055ddb814c1b36f76341356067406f97af50
|
|
BLAKE2b-256 checksum How to use checksums |
20f3f4994197271265cadc0b669db876f9b04aaab256fb1b310b5069cc4b6c53
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.9
|
Security for titanvault 1.0.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.