A framework for safety-critical operations with audit trails, locking, and approval workflows
Project description
Safeline
A Python framework for building safety-critical operations with arbitrary stage pipelines, audit trails, locking, and approval workflows.
Why Safeline?
When building tools that perform critical operations (deployments, data migrations, infrastructure changes), you need:
- Structured workflows - Break complex operations into reviewable stages
- Audit trails - Know who did what, when, and why
- Approval gates - Require sign-off before dangerous actions
- Rollback support - Undo operations when things go wrong
- Environment awareness - Different rules for prod vs dev
Safeline provides the infrastructure so you can focus on your domain logic.
Installation
pip install sfln
# With optional dependencies
pip install sfln[cli] # CLI support (click)
pip install sfln[yaml] # YAML config (pyyaml)
pip install sfln[all] # All optional deps
Quick Example
Safeline recommends a standard stage pattern for safety-critical operations:
plan -> validate -> stage -> apply -> verify
- plan - Analyze what will be done, calculate risk
- validate - Check preconditions, ensure operation is safe to proceed
- stage - Prepare resources, create backups (reversible)
- apply - Execute the actual change (requires approval in production)
- verify - Confirm the operation succeeded
from sfln import Operation, Stage, StageResult, Context, Safeline, MemoryStore
class DeployOperation(Operation):
name = "deploy"
stages = [
Stage("plan"),
Stage("validate"),
Stage("stage", reversible=True),
Stage("apply", needs_approval=True, reversible=True),
Stage("verify"),
]
def plan(self, context: Context) -> StageResult:
# Analyze what will be deployed
return StageResult(data={"targets": context.targets, "version": "2.0.0"})
def validate(self, context: Context) -> StageResult:
# Check preconditions
return StageResult(data={"valid": True})
def stage(self, context: Context) -> StageResult:
# Create backup before changes
backup_id = create_backup()
return StageResult(
data={"backup_id": backup_id},
rollback_data={"backup_id": backup_id}
)
def apply(self, context: Context) -> StageResult:
# Execute the deployment
version = context.get_stage_result("plan")["version"]
return StageResult(data={"deployed": version})
def verify(self, context: Context) -> StageResult:
# Confirm deployment succeeded
return StageResult(data={"healthy": True})
def rollback_stage(self, context: Context) -> StageResult:
return StageResult(data={"cleaned": True})
def rollback_apply(self, context: Context) -> StageResult:
backup_id = context.get_stage_result("stage")["backup_id"]
restore_from_backup(backup_id)
return StageResult(data={"restored": True})
# Run it
sl = Safeline(store=MemoryStore())
result = sl.run(DeployOperation(targets=["app-server-1"]))
print(f"Success: {result.success}")
Custom Stages
The standard stages are a recommendation, not a requirement. Define whatever stages make sense for your operation:
# Database migration with custom stages
stages = [
Stage("analyze"),
Stage("backup_schema"),
Stage("migrate", needs_approval=True),
Stage("verify_data"),
Stage("cleanup"),
]
# Simple file operation
stages = [
Stage("scan"),
Stage("execute"),
]
Key Features
Standard Stage Pattern
The recommended pattern for safety-critical operations:
stages = [
Stage("plan"), # Analyze
Stage("validate"), # Check preconditions
Stage("stage", reversible=True), # Prepare/backup
Stage("apply", needs_approval=True, reversible=True), # Execute
Stage("verify"), # Confirm success
]
Per-Stage Controls
Each stage can have its own requirements:
Stage(
name="apply",
required=True, # Operation fails if this fails
needs_approval=True, # Must be approved first
needs_lock=True, # Exclusive lock during execution
reversible=True, # Can be rolled back
timeout_seconds=300, # Max execution time
)
Audit Trail
All operations automatically emit events:
sl = Safeline(
store=MemoryStore(),
auditor=AuditStoreClient(url="http://audit-store:8080"),
)
Events: operation_created, stage_started, stage_completed, approval_granted, lock_acquired, etc.
Environment-Aware Protection
from sfln import get_protection_level
level = get_protection_level("production")
# level.require_approval = True
# level.require_backup = True
# level.allow_force = False
Development
# Setup
make quickstart
source .venv/bin/activate
# Test
make test
# Code quality
make check
make format
License
MIT
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 sfln-0.1.14.tar.gz.
File metadata
- Download URL: sfln-0.1.14.tar.gz
- Upload date:
- Size: 84.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8b2d6ea0eb87516d14a22c2ef027e9b0635d2ffbf0f2e328935b0b67bb6f1736
|
|
| MD5 |
825427dde5cf6cf464ba0e556433f145
|
|
| BLAKE2b-256 |
73694433c844fdaa72fe13d44c5ada28c88d2e976e0fc00bf4970bc27624ddbe
|
File details
Details for the file sfln-0.1.14-py3-none-any.whl.
File metadata
- Download URL: sfln-0.1.14-py3-none-any.whl
- Upload date:
- Size: 72.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f499550e80931bb5112c213b90edc6088bb7494c8536a82ff99115c8f9c09f3f
|
|
| MD5 |
27e7309d372d86e4a438e8f5752aa687
|
|
| BLAKE2b-256 |
06b7248ee6d76d7461559fb945f0cbb709109dc2c00d79812b352ac51a0760db
|