Metadata-Version: 2.4
Name: tundere-ledger
Version: 0.1.1
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Rust
Classifier: Topic :: Software Development :: Libraries :: Python Modules
License-File: LICENSE
Summary: A tamper-evident auditing ledger with Tsundere philosophy.
Keywords: audit,ledger,tamper-evident,logging,tsundere
Author: kuruitinoji
Requires-Python: >=3.8
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# Tundere Ledger 🧐

A tamper-evident auditing ledger with Tsundere philosophy.
"It's not like I'm recording this for you or anything!"

Backed by **Rust** 🦀 for strictness and performance.

## Features

- 🔒 **Tamper-Evident**: Uses SHA-256 chaining (Blockchain-like structure).
- 🚀 **High Performance**: Core logic runs in native Rust.
- 🐍 **Pythonic**: Simple `@audit_log` decorator for easy integration.

## Installation

```bash
pip install tundere-ledger
```

Or build from source:

```bash
git clone https://github.com/kuruitinoji-sys/tundere_ledger.git
cd tundere_ledger
pip install .

```

## Usage

### Basic Example: The "Tsundere" Decorator

Wrap any function to automatically record inputs, outputs, and errors.

```python
from tundere_ledger import audit_log, verify_log

@audit_log(actor_name="Maid_Chan", importance=2.0)
def delete_database(reason):
    print(f"Deleting DB because: {reason}")
    # If this raises an error, it is also recorded immutably.

# Call the function
delete_database("Master spilled coffee")

# Verify log integrity
if verify_log():
    print("Log is clean.")
else:
    print("Log has been TAMPERED with!")
```

## API Reference

### `@audit_log(actor_name="Unknown", importance=1.0, log_file="tundere_audit.jsonl")`

Decorator that automatically records function calls to an audit log.

**Parameters:**
- `actor_name` (str): Identifier of who performed the action. Default: `"Unknown"`
- `importance` (float): Importance level of the action. Used for weighted audit trails. Default: `1.0`
- `log_file` (str): Path to the audit log file. Must be within the current directory (path traversal protection). Default: `"tundere_audit.jsonl"`

**Recorded Information:**
- Function name
- Arguments and keyword arguments (converted to strings)
- Return value (on success)
- Exception details (on error)
- Timestamp (RFC3339 format)
- SHA-256 chain signature

### `verify_log(log_path="tundere_audit.jsonl") -> bool`

Verifies the integrity of an audit log using SHA-256 chaining.

**Parameters:**
- `log_path` (str): Path to the audit log file to verify. Default: `"tundere_audit.jsonl"`

**Returns:**
- `True` if the log is intact and unmodified
- `False` if the log has been tampered with or is corrupted

### `get_recorder(log_path="tundere_audit.jsonl") -> TundereRecorder`

Returns or creates a recorder instance for the specified log file.

**Parameters:**
- `log_path` (str): Path to the audit log file. Default: `"tundere_audit.jsonl"`

**Returns:**
- A `TundereRecorder` instance (Rust-backed)

## Advanced Usage

### Multiple Audit Logs

You can maintain separate audit trails for different components:

```python
from tundere_ledger import audit_log, verify_log

@audit_log(actor_name="system", log_file="payments.jsonl")
def process_payment(amount):
    pass

@audit_log(actor_name="system", log_file="user_access.jsonl")
def access_user_data(user_id):
    pass

# Verify each log independently
if verify_log("payments.jsonl"):
    print("Payment log is clean")

if verify_log("user_access.jsonl"):
    print("Access log is clean")
```

### Custom Recorder Management

```python
from tundere_ledger import get_recorder

# Get or create a recorder
recorder = get_recorder("custom_audit.jsonl")

# Manually record events
recorder.commit_truth("admin", 5.0, '{"action": "user_deleted", "user_id": 42}')

# Verify integrity
if recorder.verify_integrity():
    print("Audit trail is intact")
```

## Security Considerations

- **Path Traversal Protection**: All log file paths are validated and must reside within the current working directory.
- **Immutable Chain**: Each entry is hashed with the previous hash, making tampering immediately detectable.
- **Actor Identification**: Always specify a meaningful `actor_name` for audit traceability.

## License

MIT
