sovereign-sdk-ledger 1.3.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.
@@ -0,0 +1,197 @@
1
+ Metadata-Version: 2.4
2
+ Name: sovereign-sdk-ledger
3
+ Version: 1.3.0
4
+ Summary: Immutable, local-first, hash-chained SQLite provenance engine for ForensicReceipt Write-Side Custody
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/kenwalger/sovereign-sdk
7
+ Project-URL: Repository, https://github.com/kenwalger/sovereign-sdk
8
+ Project-URL: Changelog, https://github.com/kenwalger/sovereign-sdk/blob/main/CHANGELOG.md
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Security
13
+ Classifier: Topic :: Database
14
+ Classifier: Topic :: Software Development :: Libraries
15
+ Requires-Python: >=3.12
16
+ Description-Content-Type: text/markdown
17
+
18
+ # sovereign-ledger
19
+
20
+ **Immutable, local-first, hash-chained SQLite provenance engine for ForensicReceipt Write-Side Custody.**
21
+
22
+ `sovereign-ledger` is a zero-external-dependency Python package that stores every
23
+ `ForensicReceipt` produced by `sovereign-core` in a tamper-evident, append-only SQLite
24
+ database. It enforces Write-Side Custody through two complementary mechanisms: engine-level
25
+ SQL triggers that abort any `UPDATE` or `DELETE` at the SQLite layer, and a SHA-256 hash
26
+ chain that makes out-of-band filesystem tampering mathematically detectable.
27
+
28
+ ---
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install sovereign-sdk-ledger
34
+ ```
35
+
36
+ Requires Python 3.12 or later. Zero runtime dependencies beyond the Python standard library.
37
+
38
+ ---
39
+
40
+ ## Quick start
41
+
42
+ ```python
43
+ from sovereign_ledger import SovereignLedger
44
+
45
+ # Open (or create) the audit database
46
+ with SovereignLedger(db_path=".keys/sovereign_audit.db") as ledger:
47
+
48
+ # Append a signed ForensicReceipt after a sieve-and-sign pass
49
+ tip = ledger.append_receipt(receipt, sieved_content)
50
+
51
+ # Verify the full hash chain at any time
52
+ assert ledger.verify_ledger_integrity() # True on an untampered ledger
53
+
54
+ # Pin the sweep to a known tip to detect tail-truncation attacks
55
+ assert ledger.verify_ledger_integrity(expected_tip_hash=tip) # False if last row was deleted
56
+ ```
57
+
58
+ ---
59
+
60
+ ## API reference
61
+
62
+ ### `SovereignLedger(db_path=".keys/sovereign_audit.db")`
63
+
64
+ Opens the SQLite database at `db_path`, applies WAL journal mode, `NORMAL` synchronous
65
+ enforcement, and strict foreign-key constraints, then bootstraps the `forensic_ledger`
66
+ schema and Write-Side Custody triggers if they do not already exist. Pass `":memory:"` for
67
+ an ephemeral in-process store.
68
+
69
+ Supports the Python context manager protocol — use a `with` block to guarantee all
70
+ thread-local connection handles are released on exit.
71
+
72
+ ### `append_receipt(receipt: dict, sieved_content: str) -> str`
73
+
74
+ Derives a rolling SHA-256 `parent_hash` from the immediately preceding row's full
75
+ eight-column canonical preimage (or from the static genesis constant for the first entry)
76
+ and inserts an immutable row inside a `BEGIN IMMEDIATE` transaction. Returns the
77
+ `payload_hash` as an opaque receipt identifier.
78
+
79
+ Raises `sqlite3.IntegrityError` if `receipt["payload_hash"]` is already present (UNIQUE
80
+ constraint). Raises `sqlite3.OperationalError` if the database lock cannot be acquired
81
+ within the configured 5-second `busy_timeout`.
82
+
83
+ ### `verify_ledger_integrity(expected_tip_hash=None) -> bool`
84
+
85
+ Performs an O(n) streaming cursor sweep, re-deriving the expected `parent_hash` for every
86
+ row from its predecessor. Returns `True` if every entry is intact; `False` on the first
87
+ detected breach.
88
+
89
+ If `expected_tip_hash` is supplied, the sweep additionally asserts that the `payload_hash`
90
+ of the final ledger row matches the provided anchor, closing the tail-truncation blind spot
91
+ where an adversary drops the `BEFORE DELETE` trigger and removes trailing rows that leave
92
+ the surviving prefix chain internally consistent.
93
+
94
+ ### `close()`
95
+
96
+ Releases all thread-local SQLite connection handles tracked by this instance. The closed
97
+ flag is set atomically inside the connection-registry lock so that any concurrent thread
98
+ attempting `_get_conn()` after teardown receives a `SovereignStorageError` rather than
99
+ a leaked or dangling connection handle.
100
+
101
+ ### `SovereignStorageError`
102
+
103
+ `RuntimeError` subclass raised when any ledger operation is attempted on an instance that
104
+ has been explicitly closed. Import alongside `SovereignLedger`:
105
+
106
+ ```python
107
+ from sovereign_ledger import SovereignLedger, SovereignStorageError
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Cryptographic invariants
113
+
114
+ ### Write-Side Custody triggers
115
+
116
+ Two `BEFORE UPDATE` and `BEFORE DELETE` SQL triggers are stored inside the `.db` file
117
+ itself:
118
+
119
+ ```sql
120
+ CREATE TRIGGER prevent_update_forensic_ledger
121
+ BEFORE UPDATE ON forensic_ledger
122
+ BEGIN
123
+ SELECT RAISE(ROLLBACK, 'Write-Side Custody violation: UPDATE operations are prohibited on forensic_ledger.');
124
+ END;
125
+ ```
126
+
127
+ Any client that opens the file — Python code, a desktop SQL browser, a raw
128
+ `sqlite3.connect()` call — receives a `sqlite3.IntegrityError` and has its entire
129
+ enclosing transaction rolled back at the SQLite engine layer before any mutation lands.
130
+
131
+ ### SHA-256 hash chain
132
+
133
+ Each row stores a `parent_hash` field that is the SHA-256 digest of the immediately
134
+ preceding row's complete eight-column canonical preimage, assembled with a NUL byte
135
+ (`\x00`) delimiter between every field:
136
+
137
+ ```
138
+ parent_hash[N] = SHA-256(
139
+ "\x00".join([
140
+ row[N-1].signature,
141
+ row[N-1].payload_hash,
142
+ row[N-1].parent_hash,
143
+ row[N-1].timestamp,
144
+ str(row[N-1].raw_token_count), # "NULL" when NULL
145
+ str(row[N-1].optimized_token_count), # "NULL" when NULL
146
+ f"{float(row[N-1].tax_savings_percentage):.4f}", # "NULL" when NULL
147
+ row[N-1].sieved_content,
148
+ ])
149
+ )
150
+ ```
151
+
152
+ The NUL delimiter closes length-substitution field-boundary attacks. Fixed-precision
153
+ `:.4f` serialisation for `tax_savings_percentage` ensures that a Python `int` supplied at
154
+ append time and a SQLite `REAL` extracted at verification time both produce the identical
155
+ canonical token, preventing silent chain divergence.
156
+
157
+ Any out-of-band mutation of any stored value — textual payload, ingestion timestamp,
158
+ FinOps telemetry, or cryptographic fields — immediately breaks the chain and is detected
159
+ by `verify_ledger_integrity()`.
160
+
161
+ ---
162
+
163
+ ## Thread safety
164
+
165
+ Each thread that accesses a shared `SovereignLedger` instance receives its own isolated
166
+ `sqlite3.Connection` via the internal `_get_conn()` method. `BEGIN IMMEDIATE` and a
167
+ 5-second `busy_timeout` serialise writes at the SQLite reserved-lock level, preventing
168
+ sibling-fork `parent_hash` collisions without requiring a Python-layer mutex.
169
+
170
+ The closed-state flag is set atomically inside the connection-registry lock during
171
+ `close()`, eliminating the race window where a thread could slip past the guard and
172
+ register a dangling connection handle after teardown.
173
+
174
+ ---
175
+
176
+ ## Integration pattern
177
+
178
+ `sovereign-ledger` slots into the end of the Sovereign pipeline:
179
+
180
+ ```
181
+ [Inbound Payload]
182
+ → sovereign-sieve (Prose Tax reduction)
183
+ → sovereign-core (Ed25519 sign → ForensicReceipt)
184
+ → sovereign-ledger (append_receipt → immutable audit record)
185
+ ```
186
+
187
+ ```python
188
+ from sovereign_core import SovereignGateway
189
+ from sovereign_ledger import SovereignLedger
190
+
191
+ gateway = SovereignGateway(signing_key=".keys/sovereign_identity.pem")
192
+
193
+ with SovereignLedger(db_path=".keys/sovereign_audit.db") as ledger:
194
+ response = await gateway.sieve_and_sign(raw_payload)
195
+ tip = ledger.append_receipt(response.receipt, response.content)
196
+ assert ledger.verify_ledger_integrity(expected_tip_hash=tip)
197
+ ```
@@ -0,0 +1,180 @@
1
+ # sovereign-ledger
2
+
3
+ **Immutable, local-first, hash-chained SQLite provenance engine for ForensicReceipt Write-Side Custody.**
4
+
5
+ `sovereign-ledger` is a zero-external-dependency Python package that stores every
6
+ `ForensicReceipt` produced by `sovereign-core` in a tamper-evident, append-only SQLite
7
+ database. It enforces Write-Side Custody through two complementary mechanisms: engine-level
8
+ SQL triggers that abort any `UPDATE` or `DELETE` at the SQLite layer, and a SHA-256 hash
9
+ chain that makes out-of-band filesystem tampering mathematically detectable.
10
+
11
+ ---
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ pip install sovereign-sdk-ledger
17
+ ```
18
+
19
+ Requires Python 3.12 or later. Zero runtime dependencies beyond the Python standard library.
20
+
21
+ ---
22
+
23
+ ## Quick start
24
+
25
+ ```python
26
+ from sovereign_ledger import SovereignLedger
27
+
28
+ # Open (or create) the audit database
29
+ with SovereignLedger(db_path=".keys/sovereign_audit.db") as ledger:
30
+
31
+ # Append a signed ForensicReceipt after a sieve-and-sign pass
32
+ tip = ledger.append_receipt(receipt, sieved_content)
33
+
34
+ # Verify the full hash chain at any time
35
+ assert ledger.verify_ledger_integrity() # True on an untampered ledger
36
+
37
+ # Pin the sweep to a known tip to detect tail-truncation attacks
38
+ assert ledger.verify_ledger_integrity(expected_tip_hash=tip) # False if last row was deleted
39
+ ```
40
+
41
+ ---
42
+
43
+ ## API reference
44
+
45
+ ### `SovereignLedger(db_path=".keys/sovereign_audit.db")`
46
+
47
+ Opens the SQLite database at `db_path`, applies WAL journal mode, `NORMAL` synchronous
48
+ enforcement, and strict foreign-key constraints, then bootstraps the `forensic_ledger`
49
+ schema and Write-Side Custody triggers if they do not already exist. Pass `":memory:"` for
50
+ an ephemeral in-process store.
51
+
52
+ Supports the Python context manager protocol — use a `with` block to guarantee all
53
+ thread-local connection handles are released on exit.
54
+
55
+ ### `append_receipt(receipt: dict, sieved_content: str) -> str`
56
+
57
+ Derives a rolling SHA-256 `parent_hash` from the immediately preceding row's full
58
+ eight-column canonical preimage (or from the static genesis constant for the first entry)
59
+ and inserts an immutable row inside a `BEGIN IMMEDIATE` transaction. Returns the
60
+ `payload_hash` as an opaque receipt identifier.
61
+
62
+ Raises `sqlite3.IntegrityError` if `receipt["payload_hash"]` is already present (UNIQUE
63
+ constraint). Raises `sqlite3.OperationalError` if the database lock cannot be acquired
64
+ within the configured 5-second `busy_timeout`.
65
+
66
+ ### `verify_ledger_integrity(expected_tip_hash=None) -> bool`
67
+
68
+ Performs an O(n) streaming cursor sweep, re-deriving the expected `parent_hash` for every
69
+ row from its predecessor. Returns `True` if every entry is intact; `False` on the first
70
+ detected breach.
71
+
72
+ If `expected_tip_hash` is supplied, the sweep additionally asserts that the `payload_hash`
73
+ of the final ledger row matches the provided anchor, closing the tail-truncation blind spot
74
+ where an adversary drops the `BEFORE DELETE` trigger and removes trailing rows that leave
75
+ the surviving prefix chain internally consistent.
76
+
77
+ ### `close()`
78
+
79
+ Releases all thread-local SQLite connection handles tracked by this instance. The closed
80
+ flag is set atomically inside the connection-registry lock so that any concurrent thread
81
+ attempting `_get_conn()` after teardown receives a `SovereignStorageError` rather than
82
+ a leaked or dangling connection handle.
83
+
84
+ ### `SovereignStorageError`
85
+
86
+ `RuntimeError` subclass raised when any ledger operation is attempted on an instance that
87
+ has been explicitly closed. Import alongside `SovereignLedger`:
88
+
89
+ ```python
90
+ from sovereign_ledger import SovereignLedger, SovereignStorageError
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Cryptographic invariants
96
+
97
+ ### Write-Side Custody triggers
98
+
99
+ Two `BEFORE UPDATE` and `BEFORE DELETE` SQL triggers are stored inside the `.db` file
100
+ itself:
101
+
102
+ ```sql
103
+ CREATE TRIGGER prevent_update_forensic_ledger
104
+ BEFORE UPDATE ON forensic_ledger
105
+ BEGIN
106
+ SELECT RAISE(ROLLBACK, 'Write-Side Custody violation: UPDATE operations are prohibited on forensic_ledger.');
107
+ END;
108
+ ```
109
+
110
+ Any client that opens the file — Python code, a desktop SQL browser, a raw
111
+ `sqlite3.connect()` call — receives a `sqlite3.IntegrityError` and has its entire
112
+ enclosing transaction rolled back at the SQLite engine layer before any mutation lands.
113
+
114
+ ### SHA-256 hash chain
115
+
116
+ Each row stores a `parent_hash` field that is the SHA-256 digest of the immediately
117
+ preceding row's complete eight-column canonical preimage, assembled with a NUL byte
118
+ (`\x00`) delimiter between every field:
119
+
120
+ ```
121
+ parent_hash[N] = SHA-256(
122
+ "\x00".join([
123
+ row[N-1].signature,
124
+ row[N-1].payload_hash,
125
+ row[N-1].parent_hash,
126
+ row[N-1].timestamp,
127
+ str(row[N-1].raw_token_count), # "NULL" when NULL
128
+ str(row[N-1].optimized_token_count), # "NULL" when NULL
129
+ f"{float(row[N-1].tax_savings_percentage):.4f}", # "NULL" when NULL
130
+ row[N-1].sieved_content,
131
+ ])
132
+ )
133
+ ```
134
+
135
+ The NUL delimiter closes length-substitution field-boundary attacks. Fixed-precision
136
+ `:.4f` serialisation for `tax_savings_percentage` ensures that a Python `int` supplied at
137
+ append time and a SQLite `REAL` extracted at verification time both produce the identical
138
+ canonical token, preventing silent chain divergence.
139
+
140
+ Any out-of-band mutation of any stored value — textual payload, ingestion timestamp,
141
+ FinOps telemetry, or cryptographic fields — immediately breaks the chain and is detected
142
+ by `verify_ledger_integrity()`.
143
+
144
+ ---
145
+
146
+ ## Thread safety
147
+
148
+ Each thread that accesses a shared `SovereignLedger` instance receives its own isolated
149
+ `sqlite3.Connection` via the internal `_get_conn()` method. `BEGIN IMMEDIATE` and a
150
+ 5-second `busy_timeout` serialise writes at the SQLite reserved-lock level, preventing
151
+ sibling-fork `parent_hash` collisions without requiring a Python-layer mutex.
152
+
153
+ The closed-state flag is set atomically inside the connection-registry lock during
154
+ `close()`, eliminating the race window where a thread could slip past the guard and
155
+ register a dangling connection handle after teardown.
156
+
157
+ ---
158
+
159
+ ## Integration pattern
160
+
161
+ `sovereign-ledger` slots into the end of the Sovereign pipeline:
162
+
163
+ ```
164
+ [Inbound Payload]
165
+ → sovereign-sieve (Prose Tax reduction)
166
+ → sovereign-core (Ed25519 sign → ForensicReceipt)
167
+ → sovereign-ledger (append_receipt → immutable audit record)
168
+ ```
169
+
170
+ ```python
171
+ from sovereign_core import SovereignGateway
172
+ from sovereign_ledger import SovereignLedger
173
+
174
+ gateway = SovereignGateway(signing_key=".keys/sovereign_identity.pem")
175
+
176
+ with SovereignLedger(db_path=".keys/sovereign_audit.db") as ledger:
177
+ response = await gateway.sieve_and_sign(raw_payload)
178
+ tip = ledger.append_receipt(response.receipt, response.content)
179
+ assert ledger.verify_ledger_integrity(expected_tip_hash=tip)
180
+ ```
@@ -0,0 +1,27 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "sovereign-sdk-ledger"
7
+ version = "1.3.0"
8
+ description = "Immutable, local-first, hash-chained SQLite provenance engine for ForensicReceipt Write-Side Custody"
9
+ readme = "README.md"
10
+ requires-python = ">=3.12"
11
+ license = { text = "MIT" }
12
+ classifiers = [
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3.12",
15
+ "Intended Audience :: Developers",
16
+ "Topic :: Security",
17
+ "Topic :: Database",
18
+ "Topic :: Software Development :: Libraries",
19
+ ]
20
+
21
+ [project.urls]
22
+ Homepage = "https://github.com/kenwalger/sovereign-sdk"
23
+ Repository = "https://github.com/kenwalger/sovereign-sdk"
24
+ Changelog = "https://github.com/kenwalger/sovereign-sdk/blob/main/CHANGELOG.md"
25
+
26
+ [tool.setuptools.packages.find]
27
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,17 @@
1
+ # packages/sovereign-ledger/src/sovereign_ledger/__init__.py
2
+ """sovereign-ledger — Immutable, local-first, hash-chained SQLite provenance engine.
3
+
4
+ Provides an append-only audit ledger for ForensicReceipt transactions with
5
+ cryptographic hash-chain lineage verification and engine-level Write-Side
6
+ Custody enforcement. Zero external dependencies beyond the Python standard
7
+ library.
8
+ """
9
+
10
+ from .engine import SovereignLedger, SovereignStorageError
11
+
12
+ __version__ = "1.3.0"
13
+
14
+ __all__ = [
15
+ "SovereignLedger",
16
+ "SovereignStorageError",
17
+ ]