kilit 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kilit-0.1.0/.github/workflows/publish-to-pypi.yml +68 -0
- kilit-0.1.0/.github/workflows/tests.yml +51 -0
- kilit-0.1.0/.gitignore +54 -0
- kilit-0.1.0/CHANGELOG.md +52 -0
- kilit-0.1.0/LICENSE +21 -0
- kilit-0.1.0/MANIFEST.in +33 -0
- kilit-0.1.0/PKG-INFO +221 -0
- kilit-0.1.0/PUBLISHING.md +265 -0
- kilit-0.1.0/README.md +186 -0
- kilit-0.1.0/examples/django_example.py +112 -0
- kilit-0.1.0/examples/fastapi_example.py +272 -0
- kilit-0.1.0/examples/flask_example.py +170 -0
- kilit-0.1.0/examples/python_example.py +42 -0
- kilit-0.1.0/pyproject.toml +77 -0
- kilit-0.1.0/src/kilit/__init__.py +26 -0
- kilit-0.1.0/src/kilit/api.py +243 -0
- kilit-0.1.0/src/kilit/cli.py +600 -0
- kilit-0.1.0/src/kilit/codecs.py +355 -0
- kilit-0.1.0/src/kilit/crypto.py +405 -0
- kilit-0.1.0/src/kilit/exceptions.py +73 -0
- kilit-0.1.0/src/kilit/service.py +287 -0
- kilit-0.1.0/src/kilit/storage.py +343 -0
- kilit-0.1.0/tests/__init__.py +1 -0
- kilit-0.1.0/tests/test_cli.py +302 -0
- kilit-0.1.0/tests/test_codecs.py +125 -0
- kilit-0.1.0/tests/test_crypto.py +292 -0
- kilit-0.1.0/tests/test_storage.py +179 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
inputs:
|
|
8
|
+
test_pypi:
|
|
9
|
+
description: 'Publish to Test PyPI instead of PyPI'
|
|
10
|
+
required: false
|
|
11
|
+
type: boolean
|
|
12
|
+
default: true
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
build-and-publish:
|
|
16
|
+
name: Build and publish Python distribution to PyPI
|
|
17
|
+
runs-on: ubuntu-latest
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
|
|
23
|
+
- name: Verify tag format (only for releases)
|
|
24
|
+
if: github.event_name == 'release'
|
|
25
|
+
run: |
|
|
26
|
+
TAG="${{ github.ref_name }}"
|
|
27
|
+
if [[ ! "$TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
28
|
+
echo "Error: Tag must match v*.*.* format (e.g., v0.1.0)"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
- name: Set up Python
|
|
33
|
+
uses: actions/setup-python@v5
|
|
34
|
+
with:
|
|
35
|
+
python-version: '3.10'
|
|
36
|
+
|
|
37
|
+
- name: Install build dependencies
|
|
38
|
+
run: |
|
|
39
|
+
python -m pip install --upgrade pip
|
|
40
|
+
pip install build twine
|
|
41
|
+
|
|
42
|
+
- name: Build package
|
|
43
|
+
run: python -m build
|
|
44
|
+
|
|
45
|
+
- name: Check package
|
|
46
|
+
run: twine check dist/*
|
|
47
|
+
|
|
48
|
+
- name: Smoke test - Install and import
|
|
49
|
+
run: |
|
|
50
|
+
pip install dist/*.whl
|
|
51
|
+
python -c "import kilit; print(kilit.__version__); from kilit import Credentials; print('✅ ok')"
|
|
52
|
+
kilit --help
|
|
53
|
+
|
|
54
|
+
- name: Publish to Test PyPI
|
|
55
|
+
if: github.event_name == 'workflow_dispatch' && inputs.test_pypi
|
|
56
|
+
env:
|
|
57
|
+
TWINE_USERNAME: __token__
|
|
58
|
+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
59
|
+
run: |
|
|
60
|
+
twine upload --repository testpypi dist/*
|
|
61
|
+
|
|
62
|
+
- name: Publish to PyPI
|
|
63
|
+
if: github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && !inputs.test_pypi)
|
|
64
|
+
env:
|
|
65
|
+
TWINE_USERNAME: __token__
|
|
66
|
+
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
|
|
67
|
+
run: |
|
|
68
|
+
twine upload dist/*
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, develop ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, develop ]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
name: Test on Python ${{ matrix.python-version }}
|
|
12
|
+
runs-on: ${{ matrix.os }}
|
|
13
|
+
|
|
14
|
+
strategy:
|
|
15
|
+
fail-fast: false
|
|
16
|
+
matrix:
|
|
17
|
+
os: [ubuntu-latest, macos-latest, windows-latest]
|
|
18
|
+
python-version: ['3.10', '3.11', '3.12']
|
|
19
|
+
|
|
20
|
+
steps:
|
|
21
|
+
- name: Checkout code
|
|
22
|
+
uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: ${{ matrix.python-version }}
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: |
|
|
31
|
+
python -m pip install --upgrade pip
|
|
32
|
+
pip install -e ".[dev,yaml]"
|
|
33
|
+
|
|
34
|
+
- name: Lint with Ruff
|
|
35
|
+
run: |
|
|
36
|
+
ruff check src/
|
|
37
|
+
|
|
38
|
+
- name: Check formatting with Ruff
|
|
39
|
+
run: |
|
|
40
|
+
ruff format --check src/
|
|
41
|
+
|
|
42
|
+
- name: Run tests
|
|
43
|
+
run: |
|
|
44
|
+
pytest tests/ -v --cov=kilit --cov-report=xml --cov-report=term --cov-fail-under=60
|
|
45
|
+
|
|
46
|
+
- name: Upload coverage to Codecov
|
|
47
|
+
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'
|
|
48
|
+
uses: codecov/codecov-action@v4
|
|
49
|
+
with:
|
|
50
|
+
file: ./coverage.xml
|
|
51
|
+
fail_ci_if_error: false
|
kilit-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Kilit master keys (NEVER commit these!)
|
|
2
|
+
config/master.key
|
|
3
|
+
*.key
|
|
4
|
+
.env
|
|
5
|
+
.env.*
|
|
6
|
+
|
|
7
|
+
# Python
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
*$py.class
|
|
11
|
+
*.so
|
|
12
|
+
.Python
|
|
13
|
+
build/
|
|
14
|
+
develop-eggs/
|
|
15
|
+
dist/
|
|
16
|
+
downloads/
|
|
17
|
+
eggs/
|
|
18
|
+
.eggs/
|
|
19
|
+
lib/
|
|
20
|
+
lib64/
|
|
21
|
+
parts/
|
|
22
|
+
sdist/
|
|
23
|
+
var/
|
|
24
|
+
wheels/
|
|
25
|
+
*.egg-info/
|
|
26
|
+
.installed.cfg
|
|
27
|
+
*.egg
|
|
28
|
+
|
|
29
|
+
# Virtual environments
|
|
30
|
+
venv/
|
|
31
|
+
ENV/
|
|
32
|
+
env/
|
|
33
|
+
.venv
|
|
34
|
+
|
|
35
|
+
# Testing
|
|
36
|
+
.pytest_cache/
|
|
37
|
+
.coverage
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.hypothesis/
|
|
41
|
+
|
|
42
|
+
# IDEs
|
|
43
|
+
.vscode/
|
|
44
|
+
.idea/
|
|
45
|
+
*.swp
|
|
46
|
+
*.swo
|
|
47
|
+
*~
|
|
48
|
+
.DS_Store
|
|
49
|
+
|
|
50
|
+
# Ruff
|
|
51
|
+
.ruff_cache/
|
|
52
|
+
|
|
53
|
+
# Benchmarks
|
|
54
|
+
.benchmarks/
|
kilit-0.1.0/CHANGELOG.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Kilit will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of Kilit
|
|
12
|
+
- AES-256-GCM encryption with Scrypt KDF
|
|
13
|
+
- CLI commands: init, edit, show, export, rotate
|
|
14
|
+
- Thread-safe runtime API
|
|
15
|
+
- JSON and YAML codec support
|
|
16
|
+
- Cross-platform file permissions
|
|
17
|
+
- Django, Flask, and FastAPI integration examples
|
|
18
|
+
- Comprehensive documentation
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
- Scrypt parameters stored in envelope for deterministic decryption
|
|
22
|
+
- No master key printing by default
|
|
23
|
+
- Signal handling for temp file cleanup
|
|
24
|
+
- Safe `__repr__` methods that don't expose secrets
|
|
25
|
+
- Sanitized error messages
|
|
26
|
+
|
|
27
|
+
## [0.1.0] - 2024-02-28
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
- Initial public release
|
|
31
|
+
- Core cryptographic layer with AES-256-GCM
|
|
32
|
+
- Scrypt KDF with parameter validation
|
|
33
|
+
- Atomic file writes with fsync
|
|
34
|
+
- Cross-platform secure file permissions
|
|
35
|
+
- JSON codec (built-in)
|
|
36
|
+
- YAML codec (optional)
|
|
37
|
+
- CLI with 5 commands (init, edit, show, export, rotate)
|
|
38
|
+
- Thread-safe Credentials API
|
|
39
|
+
- Dotted path access for nested secrets
|
|
40
|
+
- Environment variable support
|
|
41
|
+
- Master key rotation
|
|
42
|
+
- Framework integration examples (Django, Flask, FastAPI)
|
|
43
|
+
- Comprehensive README and documentation
|
|
44
|
+
|
|
45
|
+
### Security
|
|
46
|
+
- Master key never printed by default
|
|
47
|
+
- Temp files cleaned up on interruption
|
|
48
|
+
- Scrypt parameters in envelope (not environment-dependent)
|
|
49
|
+
- Error messages don't leak secrets
|
|
50
|
+
|
|
51
|
+
[Unreleased]: https://github.com/erhan/kilit/compare/v0.1.0...HEAD
|
|
52
|
+
[0.1.0]: https://github.com/erhan/kilit/releases/tag/v0.1.0
|
kilit-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Erhan BÜTE
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
kilit-0.1.0/MANIFEST.in
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Include essential files
|
|
2
|
+
include README.md
|
|
3
|
+
include LICENSE
|
|
4
|
+
include CHANGELOG.md
|
|
5
|
+
include pyproject.toml
|
|
6
|
+
|
|
7
|
+
# Include source code
|
|
8
|
+
recursive-include src/kilit *.py
|
|
9
|
+
|
|
10
|
+
# Exclude unwanted files
|
|
11
|
+
global-exclude *.pyc
|
|
12
|
+
global-exclude *.pyo
|
|
13
|
+
global-exclude *.pyd
|
|
14
|
+
global-exclude __pycache__
|
|
15
|
+
global-exclude .DS_Store
|
|
16
|
+
global-exclude .git*
|
|
17
|
+
global-exclude .pytest_cache
|
|
18
|
+
global-exclude .ruff_cache
|
|
19
|
+
global-exclude *.egg-info
|
|
20
|
+
global-exclude .coverage
|
|
21
|
+
global-exclude htmlcov
|
|
22
|
+
global-exclude dist
|
|
23
|
+
global-exclude build
|
|
24
|
+
global-exclude .venv
|
|
25
|
+
global-exclude venv
|
|
26
|
+
global-exclude ENV
|
|
27
|
+
global-exclude __MACOSX
|
|
28
|
+
|
|
29
|
+
# Exclude development files
|
|
30
|
+
exclude .gitignore
|
|
31
|
+
exclude PUBLISHING.md
|
|
32
|
+
recursive-exclude examples *
|
|
33
|
+
recursive-exclude .github *
|
kilit-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: kilit
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Encrypted secrets management for Python, inspired by Rails credentials
|
|
5
|
+
Project-URL: Homepage, https://github.com/erhan/kilit
|
|
6
|
+
Project-URL: Documentation, https://github.com/erhan/kilit#readme
|
|
7
|
+
Project-URL: Repository, https://github.com/erhan/kilit
|
|
8
|
+
Project-URL: Issues, https://github.com/erhan/kilit/issues
|
|
9
|
+
Author-email: Erhan Büte <erhan@hey.com>
|
|
10
|
+
License: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: configuration,credentials,encryption,secrets,security
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: OS Independent
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Security :: Cryptography
|
|
23
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Requires-Dist: cryptography>=41.0.0
|
|
26
|
+
Requires-Dist: typer>=0.9.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: hypothesis>=6.82.0; extra == 'dev'
|
|
29
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
|
|
30
|
+
Requires-Dist: pytest>=7.4.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
32
|
+
Provides-Extra: yaml
|
|
33
|
+
Requires-Dist: pyyaml>=6.0; extra == 'yaml'
|
|
34
|
+
Description-Content-Type: text/markdown
|
|
35
|
+
|
|
36
|
+
# Kilit 🔐
|
|
37
|
+
|
|
38
|
+
Encrypted secrets management for Python, inspired by Rails credentials.
|
|
39
|
+
|
|
40
|
+
Store API keys, database passwords, and sensitive config in version control safely.
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
- 🔒 AES-256-GCM encryption with Scrypt KDF
|
|
45
|
+
- 📝 Edit secrets in your editor with auto-encryption
|
|
46
|
+
- 🔑 Multiple master key sources (file, env var, CLI)
|
|
47
|
+
- 📦 JSON and YAML support
|
|
48
|
+
- 🔄 Key rotation
|
|
49
|
+
- 🧵 Thread-safe runtime API
|
|
50
|
+
- 🌍 Cross-platform
|
|
51
|
+
|
|
52
|
+
## Installation
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pip install kilit
|
|
56
|
+
pip install kilit[yaml] # With YAML support
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Initialize
|
|
63
|
+
kilit init
|
|
64
|
+
|
|
65
|
+
# Edit secrets
|
|
66
|
+
kilit edit
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"database": {"host": "localhost", "password": "secret123"},
|
|
72
|
+
"api": {"key": "sk_live_abc123"}
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
# Use in your app
|
|
78
|
+
from kilit import Credentials
|
|
79
|
+
|
|
80
|
+
creds = Credentials("config/credentials.json.enc")
|
|
81
|
+
db_password = creds.get("database.password")
|
|
82
|
+
api_key = creds.require("api.key") # Raises if missing
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## CLI Commands
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
kilit init # Initialize
|
|
89
|
+
kilit init --format yaml # Use YAML
|
|
90
|
+
kilit init --print-master-key # Print key for CI/CD
|
|
91
|
+
|
|
92
|
+
kilit edit # Edit in $EDITOR
|
|
93
|
+
kilit show # Display secrets
|
|
94
|
+
kilit show --redact # Show structure only
|
|
95
|
+
|
|
96
|
+
eval $(kilit export) # Export as env vars
|
|
97
|
+
kilit export --prefix MYAPP_ # With prefix
|
|
98
|
+
|
|
99
|
+
kilit rotate --write-new-master-key config/master.key # Rotate key
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Runtime API
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from kilit import Credentials
|
|
106
|
+
|
|
107
|
+
creds = Credentials("config/credentials.json.enc")
|
|
108
|
+
|
|
109
|
+
# Dotted path access
|
|
110
|
+
db_host = creds.get("database.host")
|
|
111
|
+
timeout = creds.get("api.timeout", 30) # With default
|
|
112
|
+
secret = creds.require("api.key") # Raises if missing
|
|
113
|
+
|
|
114
|
+
# Reload
|
|
115
|
+
creds.reload()
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Thread-safe for concurrent access.
|
|
119
|
+
|
|
120
|
+
## Master Key Management
|
|
121
|
+
|
|
122
|
+
**Priority:** CLI arg > `KILIT_MASTER_KEY` env var > `--master-key-path` > `config/master.key`
|
|
123
|
+
|
|
124
|
+
**Development:**
|
|
125
|
+
```bash
|
|
126
|
+
echo "config/master.key" >> .gitignore
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Production:**
|
|
130
|
+
```bash
|
|
131
|
+
export KILIT_MASTER_KEY="<your-key>"
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
**CI/CD:**
|
|
135
|
+
```yaml
|
|
136
|
+
env:
|
|
137
|
+
KILIT_MASTER_KEY: ${{ secrets.KILIT_MASTER_KEY }}
|
|
138
|
+
run: eval $(kilit export) && python app.py
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## Security
|
|
142
|
+
|
|
143
|
+
- **Encryption:** AES-256-GCM with Scrypt KDF
|
|
144
|
+
- **Salt:** Unique per file (forward secrecy)
|
|
145
|
+
- **Authentication:** Tampering detection via GCM
|
|
146
|
+
|
|
147
|
+
**Protection:** Encrypted files safe in git. Secrets protected without master key. Scrypt makes brute-force expensive.
|
|
148
|
+
|
|
149
|
+
**Master key:** Single point of trust. Store securely (password manager, vault, env vars). Rotate if compromised.
|
|
150
|
+
|
|
151
|
+
**Runtime:** Secrets exist in memory during use. Follow secure coding practices.
|
|
152
|
+
|
|
153
|
+
**Permissions:** Unix systems auto-set 0600 on master key files.
|
|
154
|
+
|
|
155
|
+
## Configuration
|
|
156
|
+
|
|
157
|
+
**Scrypt (affects NEW encryptions only):**
|
|
158
|
+
```bash
|
|
159
|
+
export KILIT_SCRYPT_N=32768 # CPU/memory cost (default: 16384)
|
|
160
|
+
export KILIT_SCRYPT_R=8 # Block size (default: 8)
|
|
161
|
+
export KILIT_SCRYPT_P=1 # Parallelization (default: 1)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
**Format:** Auto-detected from extension (`.json`, `.yaml`, `.yml`). Override: `--format yaml`
|
|
165
|
+
|
|
166
|
+
## Examples
|
|
167
|
+
|
|
168
|
+
See [examples/](examples/) for Django, Flask, and FastAPI integration.
|
|
169
|
+
|
|
170
|
+
## FAQ
|
|
171
|
+
|
|
172
|
+
**Why not env vars?** Lack structure, encryption at rest, easy to expose. Kilit provides both.
|
|
173
|
+
|
|
174
|
+
**Lost master key?** No recovery by design. Store in multiple secure locations.
|
|
175
|
+
|
|
176
|
+
**Multiple files?** Yes: `Credentials("config/prod.json.enc")`
|
|
177
|
+
|
|
178
|
+
## Development
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
git clone https://github.com/erhan/kilit.git
|
|
182
|
+
cd kilit
|
|
183
|
+
uv venv && source .venv/bin/activate
|
|
184
|
+
uv pip install -e ".[dev,yaml]"
|
|
185
|
+
|
|
186
|
+
uv run pytest --cov=kilit
|
|
187
|
+
uv run ruff check .
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
**Coverage:** Goal 85%+, CI enforces 60% minimum.
|
|
191
|
+
|
|
192
|
+
## Tasks
|
|
193
|
+
|
|
194
|
+
- [ ] Increase test coverage to 85%+
|
|
195
|
+
- [ ] Add more integration tests
|
|
196
|
+
- [ ] Improve CLI test coverage
|
|
197
|
+
|
|
198
|
+
## Contributing
|
|
199
|
+
|
|
200
|
+
Contributions are welcome!
|
|
201
|
+
|
|
202
|
+
1. Fork the repository
|
|
203
|
+
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
|
204
|
+
3. Make your changes
|
|
205
|
+
4. Add tests for new functionality
|
|
206
|
+
5. Run tests: `pytest --cov=kilit`
|
|
207
|
+
6. Lint code: `ruff check . && ruff format .`
|
|
208
|
+
7. Commit: `git commit -m 'Add amazing feature'`
|
|
209
|
+
8. Push: `git push origin feature/amazing-feature`
|
|
210
|
+
9. Open a Pull Request
|
|
211
|
+
|
|
212
|
+
## Credits
|
|
213
|
+
|
|
214
|
+
Inspired by Rails credentials. Built with [cryptography](https://cryptography.io/) and [typer](https://typer.tiangolo.com/).
|
|
215
|
+
|
|
216
|
+
Special thanks to Kiro AI. 🤖✨
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
Copyright (c) 2026 Erhan Büte
|
|
221
|
+
Licensed under the MIT License.
|