The Secure, Lightweight, and Type-Safe Local Storage for the Future
Project description
🔐 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.
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 titanvault-1.0.0.tar.gz.
File metadata
- Download URL: titanvault-1.0.0.tar.gz
- Upload date:
- Size: 39.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0159005060fe11c36cca3d5c14eef0e3f1881edaeddcc31487acc166184965e3
|
|
| MD5 |
09529e6d79800c512730d46f609fb80c
|
|
| BLAKE2b-256 |
f59d8e342f4f19a131d8a7d413461953ee142459385e643704bb50251680b18d
|
File details
Details for the file titanvault-1.0.0-py3-none-any.whl.
File metadata
- Download URL: titanvault-1.0.0-py3-none-any.whl
- Upload date:
- Size: 18.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4323a1e99695a7b027d69bca5954055ddb814c1b36f76341356067406f97af50
|
|
| MD5 |
80f1e95ec0244e51eeb5f4ac8a4d3210
|
|
| BLAKE2b-256 |
20f3f4994197271265cadc0b669db876f9b04aaab256fb1b310b5069cc4b6c53
|