cinchdb 0.1.14__py3-none-any.whl → 0.1.15__py3-none-any.whl

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cinchdb
3
- Version: 0.1.14
3
+ Version: 0.1.15
4
4
  Summary: A Git-like SQLite database management system with branching and multi-tenancy
5
5
  Project-URL: Homepage, https://github.com/russellromney/cinchdb
6
6
  Project-URL: Documentation, https://russellromney.github.io/cinchdb
@@ -156,24 +156,16 @@ db.update("posts", post_id, {"content": "Updated content"})
156
156
  - **Python SDK**: Core functionality for local development
157
157
  - **CLI**: Full-featured command-line interface
158
158
 
159
- ## Security & Encryption
159
+ ## Security
160
160
 
161
- Optional transparent encryption for tenant databases:
161
+ CinchDB uses standard SQLite security features:
162
162
 
163
- ```bash
164
- # Enable encryption
165
- export CINCH_ENCRYPT_DATA=true
166
- export CINCH_ENCRYPTION_KEY="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
167
-
168
- # Install encryption library
169
- pip install pysqlcipher3
170
- ```
163
+ - **WAL mode**: Better concurrency and crash recovery
164
+ - **Foreign key constraints**: Enforced data integrity
165
+ - **File permissions**: Standard OS-level access control
166
+ - **Multi-tenant isolation**: Separate database files per tenant
171
167
 
172
- - **Tenant databases**: Encrypted with ChaCha20-Poly1305 (~2-5% overhead)
173
- - **Metadata**: Unencrypted for operational simplicity
174
- - **Integration**: Transparent - no code changes needed
175
-
176
- Works without encryption libraries - gracefully falls back to standard SQLite.
168
+ For production deployments, consider additional security measures at the infrastructure level.
177
169
 
178
170
  ## Development
179
171
 
@@ -186,14 +178,13 @@ make test
186
178
 
187
179
  ## Future
188
180
 
189
- Though probably not, perhaps I'll evolve it into something bigger and more full-featured, with things like
190
- - data backups
191
- - replication to S3
192
- - audit access
193
- - SaaS-like dynamics
194
- - multi-project hosting
195
- - auth proxying
196
- - leader-follower abilities for edge deployment
181
+ CinchDB focuses on being a simple, reliable SQLite management layer. Future development will prioritize:
182
+
183
+ - Remote API server improvements
184
+ - Better CLI user experience
185
+ - Performance optimizations
186
+ - Additional language SDKs (TypeScript, Go, etc.)
187
+ - Enhanced codegen features
197
188
 
198
189
 
199
190
  ## License
@@ -1,43 +1,44 @@
1
- cinchdb/__init__.py,sha256=m-yJkJh1kFCBWHjgEi9Aqz7LrrxlhRWc13Daa8PJv74,477
1
+ cinchdb/__init__.py,sha256=qnBv5kpL4GJjNbQkp-nBcOgrsskwDr7WTnUPCGwg3zs,603
2
2
  cinchdb/__main__.py,sha256=OpkDqn9zkTZhhYgvv_grswWLAHKbmxs4M-8C6Z5HfWY,85
3
3
  cinchdb/config.py,sha256=gocjMnYKLWhgvnteo6zprgwtK6Oevoxq547J_v-C9Ns,5265
4
4
  cinchdb/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- cinchdb/cli/main.py,sha256=G26O3EqOaKwOfwkOXOfp2XgyS5fslMgKidOAgW5k6qU,4764
5
+ cinchdb/cli/main.py,sha256=x2bF19e0lY_0V3_tx6CO9M3AaFlII75bAdWaOg0ne_A,4587
6
6
  cinchdb/cli/utils.py,sha256=InAGuo7uENvsfBQu6EKIbbiNXqmvg-BecLmhLvOz5qg,6485
7
- cinchdb/cli/commands/__init__.py,sha256=IRUIPHgdpF4hBDbDy0SgaWn39o5GNUjH54_C42sjlQg,273
7
+ cinchdb/cli/commands/__init__.py,sha256=Wjj_cmfscb_mpC-yFXxWW0-pJoBlI-Vpunb37SARsTs,291
8
8
  cinchdb/cli/commands/branch.py,sha256=Nz8YQYJ7lizSXEAv0usTx85TDOC-N5Ul9KIxN8JQtKc,17973
9
9
  cinchdb/cli/commands/codegen.py,sha256=WsRWmXNTDuaLPyECW5psXM9zOQnKHpUiv8BJnBAjMII,6189
10
10
  cinchdb/cli/commands/column.py,sha256=nUVgjYbxSobJR9CC-qdOvrCl1TgFySr-ctQb0djKZtQ,11676
11
+ cinchdb/cli/commands/data.py,sha256=tRXVeYCShVp5VKJ--Q_XzTokPE6G0gaHSad48iFHa3E,12662
11
12
  cinchdb/cli/commands/database.py,sha256=A3ew8Z987a25dRxmY5XeoB-Ka6SXLKtWogj3XAKUNZE,7332
12
- cinchdb/cli/commands/index.py,sha256=P0sM9lu1rVliacYl49LPqtxNYdrwzKzpVKW10jC-5i4,6096
13
+ cinchdb/cli/commands/index.py,sha256=qL3-UOk_cBLBNR4qK2uPTyFI7qAMxQSE7YtXFXNeSdg,6094
13
14
  cinchdb/cli/commands/query.py,sha256=XW_YL6M5IYHHHMpVB5p-M01kawFxwDOK5B5hGIy_BA8,5044
14
15
  cinchdb/cli/commands/remote.py,sha256=i07hfiAxgrROB9lVJVaKK_nWxT1SGiSbtFb4jvEwxEo,4445
15
16
  cinchdb/cli/commands/table.py,sha256=K233WOV102-g6QlHhL97FhfiGz67zIctbxZblAjY4Lg,10516
16
- cinchdb/cli/commands/tenant.py,sha256=cOWs9Gf13ZE4KTKJZ_AvDwFDdXBUn5i-Av4MoUsc8Go,6199
17
+ cinchdb/cli/commands/tenant.py,sha256=snpMc9Jk2uGmEJCKP39zD26BZLYBhiRxP2M5oGyz0rQ,8309
17
18
  cinchdb/cli/commands/view.py,sha256=ZmS1IW7idzzHAXmgVyY3C4IQRo7toHb6fHNFY_tQJjI,6385
18
19
  cinchdb/cli/handlers/__init__.py,sha256=f2f-Cc96rSBLbVsiIbf-b4pZCKZoHfmhNEvnZ0OurRs,131
19
20
  cinchdb/cli/handlers/codegen_handler.py,sha256=i5we_AbiUW3zfO6pIKWxvtO8OvOqz3H__4xPmTLEuQM,6524
20
21
  cinchdb/core/__init__.py,sha256=iNlT0iO9cM0HLoYwzBavUBoXRh1Tcnz1l_vfbwVxK_Q,246
21
- cinchdb/core/connection.py,sha256=x_xMJv1DiZtWjBoSa2rJSGHs_m6pbtk2JYIYTdeWMtE,5491
22
- cinchdb/core/database.py,sha256=vzVr6Y6iydf9kOU0OO7yVYoHQJ3zlfwAWF2LylJUV0I,27162
22
+ cinchdb/core/connection.py,sha256=FdYVQuoFYo7B0JSHfCTZFTq3DkM_NWHF4ei-fMyyEMI,5171
23
+ cinchdb/core/database.py,sha256=K5zPG8wXdh9-jAg69QZ7ImE0u3qAuvCDulfAx1fOq5U,33307
23
24
  cinchdb/core/initializer.py,sha256=CAzq947plgEF-KXV-PD-ycJ8Zy4zXCQqCrmQ0-pV0i4,14474
24
25
  cinchdb/core/maintenance.py,sha256=PAgrSL7Cj9p3rKHV0h_L7gupN6nLD0-5eQpJZNiqyEs,2097
25
- cinchdb/core/path_utils.py,sha256=OPT5WGx6CPdjZbvNsB5fjJGKsl5RtW8-IFacE4TWSxA,4884
26
- cinchdb/infrastructure/metadata_connection_pool.py,sha256=oq4z2B43_kEPUA0QVZz6AI_xl4adOuOSJ7VeZ7ecmP4,4899
27
- cinchdb/infrastructure/metadata_db.py,sha256=QLVHtvto9c2yJw7022JXwfaEilS-k-OICsbHQvA6QSQ,15314
26
+ cinchdb/core/path_utils.py,sha256=Va4y2Dkd5QI6FI5h1ePyVH5pwr7tzRpYZLA4KEpDV0Q,4874
27
+ cinchdb/infrastructure/metadata_connection_pool.py,sha256=PeVsyuZKdI3Y7_InWMOn9HcSNhE0MVcP7I7wAj9esmI,4859
28
+ cinchdb/infrastructure/metadata_db.py,sha256=t3WDyE9SjWhTB2S0-v82AmWKXfl1571V_dv4Bv1-u10,15894
28
29
  cinchdb/managers/__init__.py,sha256=ic61ZUdsg-muq0ETYO6fuZRQWF4j7l920PthTkt2QrE,808
29
- cinchdb/managers/branch.py,sha256=ctX2RpodtQ-fLMpGzHyJMydseb0rK4gLjMz2ix82seU,9455
30
+ cinchdb/managers/branch.py,sha256=bEzl83mN9a9KW8AHC_w50QHtVdVPHUzEY-j9T2EAyR4,9445
30
31
  cinchdb/managers/change_applier.py,sha256=cCgjUL6SJvrgVCCHAw0mAbGqZqKmMsLa0QbziSiuW68,15576
31
32
  cinchdb/managers/change_comparator.py,sha256=08pwybpSt36cFwhZRSIkHynvFMUaLKEVwa8Ajn_R9yQ,6862
32
33
  cinchdb/managers/change_tracker.py,sha256=U93BPnuGv8xSaO5qr_y5Q8ppKrVXygozdp5zUvLUqwg,5054
33
34
  cinchdb/managers/codegen.py,sha256=1CfIwjgHnNDdjrq4SzQ9VE7DFgnWfk7RtpupBFUTqxk,21804
34
35
  cinchdb/managers/column.py,sha256=i0EzDKavMvZeeaVrY9OVRNHOW60v0rUEkDjMtIs3PaE,20749
35
- cinchdb/managers/data.py,sha256=zS1HkMGf436m6f8VdFAqQbQFgo4sL5yKJRcRf4A6lIc,16253
36
- cinchdb/managers/index.py,sha256=n9bCXggZP6muJQZXCpTT46JvuvcbbnYgeV3j6iXtTVM,10371
36
+ cinchdb/managers/data.py,sha256=9JAcJ1bxTKb15s0Zb0ATH4YW-6O03iSvyJnk1SsDq80,23170
37
+ cinchdb/managers/index.py,sha256=55_fafWd4lSju4Nw32B_1Fi1c2DPHxOgAhdsqcTR404,10343
37
38
  cinchdb/managers/merge_manager.py,sha256=R8S2hLkLJg4hLDpeJTzjVkduZgqPOjXtYgOSJhTXXrE,15690
38
- cinchdb/managers/query.py,sha256=mBWsWjdAqWDzuvxKsY49onAOP6dsZOMhVKwA7Y1kunE,8617
39
- cinchdb/managers/table.py,sha256=8w6L4-DJgvsvpTYDW123Y9JuXO95O-SfOs-XMqWSvzA,14028
40
- cinchdb/managers/tenant.py,sha256=szmgErdqs3KXPi5LugMnUR76PxWARMj6H6y-JvcYd68,33965
39
+ cinchdb/managers/query.py,sha256=hgNHda20PWMijbVRnjTKFGFBvBthep2fulkJEK1gkqU,8562
40
+ cinchdb/managers/table.py,sha256=GgwW_lVl9qmbr5x6JXDdvTBL_Ylkk4AzAD2HXQAOH0E,15246
41
+ cinchdb/managers/tenant.py,sha256=Oy60CKWTgDetF_SpbTFcS8bjumlNjEInd_APRg86f5M,31628
41
42
  cinchdb/managers/view.py,sha256=v9gYtRufZyxywPKLGvIjvlUXcxYh9CLRArefu9QX6zk,7809
42
43
  cinchdb/models/__init__.py,sha256=cZ-ailJ6qu44Iap5Rq555iB-_w9ufXVDBH3rDH-ojk0,622
43
44
  cinchdb/models/base.py,sha256=7j4rlFTP5K9ZuF8vxwC7lMFEaL7O90NJ47Ig5i7ubcw,1320
@@ -48,13 +49,15 @@ cinchdb/models/project.py,sha256=6GMXUZUsEIebqQJgRXIthWzpWKuNNmJ3drgI1vFDrMo,644
48
49
  cinchdb/models/table.py,sha256=nxf__C_YvDOW-6-vdOQ4xKmwWPZwgEdYw1I4mO_C44o,2955
49
50
  cinchdb/models/tenant.py,sha256=wTvGoO_tQdtueVB0faZFVIhSjh_DNJzywflrUpngWTM,1072
50
51
  cinchdb/models/view.py,sha256=q6j-jYzFJuhRJO87rKt6Uv8hOizHQx8xwoPKoH6XnNY,530
51
- cinchdb/security/__init__.py,sha256=GWV6OIczkPhJazLvMFcT54aDUI6_mU9MTZu09TEGrJ0,45
52
- cinchdb/security/encryption.py,sha256=nEmjNot2NyJZivrsf4jYB9Ei-LJdb2_O6BfXsO9-pww,4168
52
+ cinchdb/plugins/__init__.py,sha256=cpqB9y9sY6b9N5Gy9f78Zd2LJ-VpRnwEMS6GpQeW-KY,301
53
+ cinchdb/plugins/base.py,sha256=f0WOTVOLAqWLOSKI6GSNLhHN-wziBGWJza7z1QH0_MY,3038
54
+ cinchdb/plugins/decorators.py,sha256=vSTDC3TDywqDi8Da5aoKe7rRVA2EbTuJXAk6VV4BosM,1533
55
+ cinchdb/plugins/manager.py,sha256=1GcDhCwJvdkXSrgYe-jGA7g8NJNyYk0037_tMNugijE,6807
53
56
  cinchdb/utils/__init__.py,sha256=yQQhEjndDiB2SUJybUmp9dvEOQKiR-GySe-WiCius5E,490
54
57
  cinchdb/utils/name_validator.py,sha256=dyGX5bjlTFRA9EGrWRQKp6kR__HSV04hLV5VueJs4IQ,4027
55
58
  cinchdb/utils/sql_validator.py,sha256=aWOGlPX0gBkuR6R1EBP2stbP4PHZuI6FUBi2Ljx7JUI,5815
56
- cinchdb-0.1.14.dist-info/METADATA,sha256=uNJzcdK2TKRlTyob3Kpf9mJQldTrxw-nDJcqOiz9wAo,6116
57
- cinchdb-0.1.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
58
- cinchdb-0.1.14.dist-info/entry_points.txt,sha256=VBOIzvnGbkKudMCCmNORS3885QSyjZUVKJQ-Syqa62w,47
59
- cinchdb-0.1.14.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
60
- cinchdb-0.1.14.dist-info/RECORD,,
59
+ cinchdb-0.1.15.dist-info/METADATA,sha256=LdviGmMLfCUhko3Y6v9ViCFPVaX9KtiXv_ZwGhKwwlo,5958
60
+ cinchdb-0.1.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
61
+ cinchdb-0.1.15.dist-info/entry_points.txt,sha256=VBOIzvnGbkKudMCCmNORS3885QSyjZUVKJQ-Syqa62w,47
62
+ cinchdb-0.1.15.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
63
+ cinchdb-0.1.15.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- """Security module for CinchDB encryption."""
@@ -1,108 +0,0 @@
1
- """Simple SQLite encryption using environment variables with KMS upgrade path."""
2
-
3
- import os
4
- import sqlite3
5
- import logging
6
- from pathlib import Path
7
-
8
- logger = logging.getLogger(__name__)
9
-
10
-
11
- class SQLiteEncryption:
12
- """Simple SQLite encryption with static keys and KMS upgrade path."""
13
-
14
- def __init__(self):
15
- # Encryption is optional for open source users
16
- self.enabled = os.getenv("CINCH_ENCRYPT_DATA", "false").lower() == "true"
17
- self._encryption_key = None
18
-
19
- if self.enabled:
20
- self._encryption_key = self._get_encryption_key()
21
-
22
- def _get_encryption_key(self) -> str:
23
- """Get encryption key with future KMS support."""
24
-
25
- # Future KMS support - check for KMS configuration first
26
- kms_provider = os.getenv("CINCH_KMS_PROVIDER")
27
- if kms_provider:
28
- # TODO: Implement KMS key retrieval
29
- # return self._get_key_from_kms(kms_provider)
30
- logger.warning("KMS provider configured but not implemented yet")
31
-
32
- # Require explicit key
33
- static_key = os.getenv("CINCH_ENCRYPTION_KEY")
34
- if static_key:
35
- return static_key
36
-
37
- # Fail fast if no key provided
38
- raise ValueError(
39
- "CINCH_ENCRYPTION_KEY environment variable is required when CINCH_ENCRYPT_DATA=true. "
40
- "Generate a key with: python -c \"import secrets; print(secrets.token_urlsafe(32))\""
41
- )
42
-
43
- def get_connection(self, db_path: Path) -> sqlite3.Connection:
44
- """Get SQLite connection with optional encryption."""
45
- # Connect with datetime parsing support
46
- conn = sqlite3.connect(
47
- str(db_path),
48
- detect_types=sqlite3.PARSE_DECLTYPES | sqlite3.PARSE_COLNAMES,
49
- )
50
-
51
- if self.enabled and self._encryption_key:
52
- try:
53
- # Apply encryption key
54
- conn.execute(f"PRAGMA key = '{self._encryption_key}'")
55
-
56
- # Configure recommended cipher (ChaCha20-Poly1305) if supported
57
- try:
58
- conn.execute("PRAGMA cipher = 'chacha20'")
59
- except sqlite3.OperationalError:
60
- # Fallback to default cipher if ChaCha20 not available
61
- logger.debug("ChaCha20 cipher not available, using default")
62
-
63
- # Security hardening
64
- conn.execute("PRAGMA temp_store = MEMORY") # Encrypt temp data
65
- conn.execute("PRAGMA secure_delete = ON") # Overwrite deleted data
66
-
67
- except sqlite3.OperationalError as e:
68
- logger.error(f"Failed to apply encryption to {db_path}: {e}")
69
- # Close connection and re-raise with helpful message
70
- conn.close()
71
- raise sqlite3.OperationalError(
72
- f"Failed to apply encryption. Make sure SQLite3MultipleCiphers is installed. Error: {e}"
73
- ) from e
74
-
75
- # Standard SQLite optimizations
76
- conn.execute("PRAGMA journal_mode = WAL")
77
- conn.execute("PRAGMA synchronous = NORMAL")
78
- conn.execute("PRAGMA cache_size = -2000")
79
-
80
- return conn
81
-
82
- def is_encrypted(self, db_path: Path) -> bool:
83
- """Check if database file is encrypted."""
84
- if not db_path.exists():
85
- return False
86
-
87
- try:
88
- # Try to open without key
89
- test_conn = sqlite3.connect(str(db_path))
90
- test_conn.execute("SELECT name FROM sqlite_master LIMIT 1")
91
- test_conn.close()
92
- return False # Successfully opened = not encrypted
93
- except sqlite3.DatabaseError:
94
- return True # Failed to open = likely encrypted
95
-
96
- def test_encryption_support(self) -> bool:
97
- """Test if SQLite encryption is available."""
98
- try:
99
- conn = sqlite3.connect(':memory:')
100
- conn.execute("PRAGMA key = 'test'")
101
- conn.close()
102
- return True
103
- except sqlite3.OperationalError:
104
- return False
105
-
106
-
107
- # Global instance for easy access
108
- encryption = SQLiteEncryption()