LPIC - Local-First Identity & Policy Core
A zero-cloud, SQLite-backed identity + policy + audit engine that runs entirely locally.
What is LPIC?
LPIC is a dependency-grade authorization primitive designed for offline, air-gapped, and edge environments. It provides cryptographically sound identity management, policy-based authorization, and tamper-evident audit logging without any cloud dependencies.
Core Questions LPIC Answers
- Who is making a request?
- What resource is being accessed?
- What action is requested?
- Under what conditions should this be allowed?
- Should it be ALLOW / DENY / REQUIRE_REVIEW?
- Log every decision immutably.
What LPIC Is NOT
- ❌ OAuth / SSO / Web auth
- ❌ Token server
- ❌ Cloud IAM
- ❌ Network service
LPIC is a local authorization library that embeds into your application.
Features
1️⃣ Cryptographic Identity
- Ed25519 keypairs: Industry-standard elliptic curve cryptography
- Identity derivation: Identity ID = SHA-256(public_key)
- Signature verification: All requests must be cryptographically signed
- Local key storage: Private keys never leave the device
2️⃣ Policy-Based Authorization
Policies support:
- Subject: Identity ID or role (supports wildcards)
- Resource: Resource identifier (supports wildcards like
files/*) - Action: read, write, execute, delete, admin
- Decision: ALLOW, DENY, REQUIRE_REVIEW
- Conditions:
- Time windows
- Device restrictions
- Metadata requirements
3️⃣ Deterministic Evaluation
- Pure functions: No side effects in policy evaluation
- Canonical JSON: Deterministic serialization
- Stable ordering: Same request → same decision
- Precedence rules: DENY > REQUIRE_REVIEW > ALLOW
- Default DENY: No implicit allows
4️⃣ Tamper-Evident Audit Log
- Hash chaining: Each entry links to previous entry
- Append-only: Cannot modify past entries without detection
- Integrity verification: Cryptographic proof of tampering
- Complete history: Every decision is logged
Installation
pip install -e . --break-system-packages
Quick Start
from lpic import LPICEngine, Keypair, sign_request
# Initialize engine
engine = LPICEngine("authorization.db")
# Generate and register identity
keypair = Keypair.generate()
identity_id = engine.register_identity(keypair)
# Add authorization policy
engine.add_policy(
subject=identity_id,
resource="file://data.txt",
action="read",
decision="ALLOW",
)
# Create and authorize request
request = sign_request(
keypair=keypair,
resource="file://data.txt",
action="read",
context={},
)
decision = engine.authorize(request)
print(f"Decision: {decision}") # ALLOW
# Verify audit integrity
engine.verify_audit_integrity()
print("Audit log is intact")
engine.close()
Architecture
lpic/
├── engine.py # Public API
├── invariants.py # Runtime validation
├── errors.py # Domain exceptions
├── config.py # Constants
│
├── identity/
│ ├── keypair.py # Ed25519 key management
│ ├── identity_store.py # Identity storage
│ └── signature.py # Request signing
│
├── policy/
│ ├── model.py # Policy schema
│ ├── evaluator.py # Deterministic evaluation
│ └── conditions.py # Context constraints
│
├── audit/
│ ├── log_schema.py # Audit entry structure
│ ├── recorder.py # Decision recording
│ └── integrity.py # Hash-chain verification
│
├── db/
│ ├── connection.py # SQLite management
│ ├── schema.py # Database schema
│ └── migrations.py # Schema versioning
│
└── utils/
├── hashing.py # SHA-256 operations
├── canonical_json.py # Deterministic JSON
└── time.py # Monotonic timestamps
Usage Examples
Identity Management
from lpic import LPICEngine, Keypair
engine = LPICEngine("auth.db")
# Generate new identity
keypair = Keypair.generate()
identity_id = engine.register_identity(
keypair,
metadata={"name": "Alice", "role": "admin"}
)
# Save private key (secure storage)
keypair.save_to_file("alice.pem")
# Load existing keypair
keypair = Keypair.load_from_file("alice.pem")
Policy Management
# Allow specific identity to read specific file
engine.add_policy(
subject="abc123...",
resource="file://secret.txt",
action="read",
decision="ALLOW",
)
# Allow all identities to read public files
engine.add_policy(
subject="*",
resource="public/*",
action="read",
decision="ALLOW",
)
# Require review for admin actions
engine.add_policy(
subject="*",
resource="*",
action="admin",
decision="REQUIRE_REVIEW",
)
# Time-based access
engine.add_policy(
subject="abc123...",
resource="file://temp.txt",
action="write",
decision="ALLOW",
conditions={
"time_window": {
"start": "2025-01-01T00:00:00.000000Z",
"end": "2025-12-31T23:59:59.999999Z",
}
}
)
# Device-restricted access
engine.add_policy(
subject="abc123...",
resource="file://secure.txt",
action="read",
decision="ALLOW",
conditions={
"device_id": ["device-001", "device-002"]
}
)
Authorization
from lpic import sign_request
# Create signed request
request = sign_request(
keypair=keypair,
resource="file://data.txt",
action="read",
context={
"device_id": "device-001",
"metadata": {"reason": "data analysis"}
}
)
# Authorize
decision = engine.authorize(request)
if decision == "ALLOW":
print("Access granted")
elif decision == "DENY":
print("Access denied")
elif decision == "REQUIRE_REVIEW":
print("Manual review required")
Audit Log
# Get all audit entries
audit_log = engine.get_audit_log()
# Filter by identity
user_log = engine.get_audit_log(identity_id="abc123...")
# Filter by resource
resource_log = engine.get_audit_log(resource="file://secret.txt")
# Verify integrity
try:
engine.verify_audit_integrity()
print("Audit log is intact")
except AuditChainBrokenError:
print("WARNING: Audit log has been tampered with!")
# Get summary
summary = engine.get_audit_summary()
print(f"Total entries: {summary['total_entries']}")
print(f"Valid: {summary['is_valid']}")
Security Model
Core Security Invariants
-
Identity is cryptographically bound to keypair
- Identity ID = SHA-256(public_key)
- Cannot forge identity without private key
-
Private keys never leave local device
- Keys stored in local files or secure containers
- No network transmission
-
Policies are deterministic and pure
- Same input → same output
- No side effects
- Reproducible evaluation
-
Every authorization decision is auditable
- Complete audit trail
- Tamper detection via hash chains
- Append-only log
-
No implicit allow
- Default decision is DENY
- Explicit policies required
-
Signatures cannot be forged
- Ed25519 cryptographic signatures
- Request integrity verified
Testing
Run the comprehensive test suite:
cd lpic
pytest tests/ -v
Tests verify:
- ✅ Signature validation correctness
- ✅ Policy denies by default
- ✅ Deterministic decisions
- ✅ Audit chain integrity
- ✅ Tamper detection
- ✅ Replay determinism
- ✅ Edge case rejection
- ✅ Invariant violation detection
API Reference
LPICEngine
Main engine class for authorization.
engine = LPICEngine(db_path: str)
Identity Management:
register_identity(keypair, metadata=None) -> strget_identity(identity_id) -> dictlist_identities() -> list[dict]
Policy Management:
add_policy(subject, resource, action, decision, conditions=None) -> strget_policy(policy_id) -> dictlist_policies() -> list[dict]delete_policy(policy_id)
Authorization:
authorize(request: SignedRequest) -> strauthorize_dict(request_dict) -> str
Audit Log:
get_audit_entry(entry_id) -> dictget_audit_log(identity_id=None, resource=None) -> list[dict]verify_audit_integrity() -> boolget_audit_summary() -> dict
Utilities:
health_check() -> dictclose()
Keypair
Ed25519 keypair management.
keypair = Keypair.generate()
keypair = Keypair.load_from_file(path)
Methods:
get_identity_id() -> strget_public_bytes() -> bytesget_private_bytes() -> bytessave_to_file(path)
SignedRequest
Cryptographically signed authorization request.
request = sign_request(keypair, resource, action, context)
Attributes:
identity_id: strresource: straction: strcontext: dictsignature: bytes
Configuration
Constants are defined in lpic/config.py:
- Hash Algorithm: SHA-256
- Signature Algorithm: Ed25519
- Valid Decisions: ALLOW, DENY, REQUIRE_REVIEW
- Valid Actions: read, write, execute, delete, admin
Performance Considerations
LPIC prioritizes correctness over speed:
- Policy evaluation is O(n) where n = number of policies
- Audit log writes are sequential for integrity
- Hash chain verification is O(n) where n = number of entries
- SQLite provides excellent performance for local operations
For high-performance scenarios, cache policies and batch operations.
Limitations
- No distributed consensus: Single-node only
- No automatic sync: Must implement sync layer if needed
- SQLite limitations: ~1M writes/sec, 140 TB max database
- No automatic key rotation: Must implement key management
Why LPIC is Secure by Construction
LPIC's security is achieved through multiple layers of defense:
Immutability
- Audit log is append-only: Past entries cannot be modified without breaking the hash chain
- Hash chaining: Each entry cryptographically links to all previous entries
- Canonical serialization: Ensures identical data always produces identical hashes
- Monotonic timestamps: Time cannot go backwards, preventing temporal attacks
Deterministic Evaluation
- Pure functions: Policy evaluation has zero side effects
- Stable ordering: Policy precedence rules are explicit and consistent
- Canonical JSON: Eliminates serialization non-determinism
- No hidden state: All evaluation inputs are explicit
Cryptographic Guarantees
- Ed25519 signatures: Industry-standard elliptic curve cryptography
- Identity binding: Identity ID derived directly from public key (cannot be forged)
- SHA-256 hashing: Collision-resistant hashing for integrity
- Request signing: Every request must be cryptographically signed
Explicit Denial Model
- Default DENY: No policies = access denied
- No implicit allows: Every ALLOW must be explicitly granted
- Precedence rules: DENY always wins in conflicts
- Signature required: Unsigned requests are rejected
Runtime Invariant Validation
- Identity binding verification: Identity must match public key
- Signature validation: Every request signature is verified
- Decision validation: Only valid decisions accepted
- Format validation: Hashes, IDs, and timestamps are validated
- Chain integrity: Audit log integrity checked on demand
Design Principles
- Fail securely: Errors default to DENY
- Explicit over implicit: All security decisions are explicit
- Verifiable: All security properties can be verified
- Auditable: Complete decision history
- Offline-first: No network dependencies
These properties make LPIC suitable for:
- Air-gapped environments
- Safety-critical systems
- Compliance-sensitive applications
- Edge computing
- Embedded systems
- Security research
License & Enterprise Usage
This project is open-source for personal, educational, and non-commercial use under the MIT License.
Enterprise & Commercial Use
For enterprise or commercial deployments, a nominal licensing fee applies. This ensures sustainable development and priority support.
Please contact Shivay (or create a GitHub issue) for enterprise licensing details. We offer:
- Commercial-friendly license
- Priority bug fixes
- Custom feature development
- Integration support
Contributing
This is a standalone reference implementation. For production use, conduct thorough security review and testing for your specific use case.
Metadata
Release files for lpic 0.1.2
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 | |
|---|---|---|---|---|
| lpic-0.1.2.tar.gz | 38.2 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lpic-0.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 77.3 kB
Release files / lpic-0.1.2.tar.gz
| Download URL | lpic-0.1.2.tar.gz |
|---|---|
| Size | 38.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
13cb949ff824c916f78dac6b2ce7467e91394108c334953a7668f91e93e4757f
|
|
BLAKE2b-256 checksum How to use checksums |
fe122a6803828f334f4173e33c68d97cdfe08900270eaf0b056a92bb4cac2e4f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|
Release files / lpic-0.1.2-py3-none-any.whl
| Download URL | lpic-0.1.2-py3-none-any.whl |
|---|---|
| Size | 39.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e83a99cf7782ab0e68968db68a526715cd737f152db956693fc0317894a67bd2
|
|
BLAKE2b-256 checksum How to use checksums |
5f6562f6dbf7f7e3765c5b86d077cab0b09db1fd8efcbcaa7f4f3da454a4c6c2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.12.6
|
Security for lpic 0.1.2
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.