sealrun 0.5.0rc1__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.
- sealrun-0.5.0rc1/LICENSE +21 -0
- sealrun-0.5.0rc1/PKG-INFO +9 -0
- sealrun-0.5.0rc1/README.md +401 -0
- sealrun-0.5.0rc1/pyproject.toml +19 -0
- sealrun-0.5.0rc1/sealrun/__init__.py +5 -0
- sealrun-0.5.0rc1/sealrun/anchor.py +1214 -0
- sealrun-0.5.0rc1/sealrun/beef.py +576 -0
- sealrun-0.5.0rc1/sealrun/broadcast.py +353 -0
- sealrun-0.5.0rc1/sealrun/bsv.py +725 -0
- sealrun-0.5.0rc1/sealrun/checkpoint_cache.py +941 -0
- sealrun-0.5.0rc1/sealrun/checkpoint_seq.py +23 -0
- sealrun-0.5.0rc1/sealrun/cli.py +1395 -0
- sealrun-0.5.0rc1/sealrun/core.py +2434 -0
- sealrun-0.5.0rc1/sealrun/launcher.py +1603 -0
- sealrun-0.5.0rc1/sealrun/proof_bundle.py +359 -0
- sealrun-0.5.0rc1/sealrun/publisher.py +1377 -0
- sealrun-0.5.0rc1/sealrun/publishing.py +221 -0
- sealrun-0.5.0rc1/sealrun/signer_cli.py +1346 -0
- sealrun-0.5.0rc1/sealrun/spv.py +1519 -0
- sealrun-0.5.0rc1/sealrun/v2_anchor.py +401 -0
- sealrun-0.5.0rc1/sealrun.egg-info/PKG-INFO +9 -0
- sealrun-0.5.0rc1/sealrun.egg-info/SOURCES.txt +70 -0
- sealrun-0.5.0rc1/sealrun.egg-info/dependency_links.txt +1 -0
- sealrun-0.5.0rc1/sealrun.egg-info/entry_points.txt +2 -0
- sealrun-0.5.0rc1/sealrun.egg-info/requires.txt +3 -0
- sealrun-0.5.0rc1/sealrun.egg-info/top_level.txt +1 -0
- sealrun-0.5.0rc1/setup.cfg +4 -0
- sealrun-0.5.0rc1/tests/test_adversarial_repro.py +131 -0
- sealrun-0.5.0rc1/tests/test_anchor.py +148 -0
- sealrun-0.5.0rc1/tests/test_anchor_cli.py +31 -0
- sealrun-0.5.0rc1/tests/test_anchor_signature.py +403 -0
- sealrun-0.5.0rc1/tests/test_beef.py +868 -0
- sealrun-0.5.0rc1/tests/test_bsv.py +481 -0
- sealrun-0.5.0rc1/tests/test_bsv_pass_fixes.py +664 -0
- sealrun-0.5.0rc1/tests/test_bump.py +456 -0
- sealrun-0.5.0rc1/tests/test_canonical_json_hardening.py +43 -0
- sealrun-0.5.0rc1/tests/test_core.py +359 -0
- sealrun-0.5.0rc1/tests/test_core_review_fixes.py +229 -0
- sealrun-0.5.0rc1/tests/test_finding_b_daa.py +387 -0
- sealrun-0.5.0rc1/tests/test_fuzz_parsers.py +538 -0
- sealrun-0.5.0rc1/tests/test_header_chain.py +345 -0
- sealrun-0.5.0rc1/tests/test_issue11_acceptance_binding.py +446 -0
- sealrun-0.5.0rc1/tests/test_issue8_anchor_chain.py +387 -0
- sealrun-0.5.0rc1/tests/test_issue9_release_seq.py +404 -0
- sealrun-0.5.0rc1/tests/test_keygen.py +117 -0
- sealrun-0.5.0rc1/tests/test_launcher.py +577 -0
- sealrun-0.5.0rc1/tests/test_mainnet_network.py +435 -0
- sealrun-0.5.0rc1/tests/test_manifest_secp256k1.py +258 -0
- sealrun-0.5.0rc1/tests/test_minimax_repro.py +93 -0
- sealrun-0.5.0rc1/tests/test_payload_binding.py +615 -0
- sealrun-0.5.0rc1/tests/test_proof_bundle.py +248 -0
- sealrun-0.5.0rc1/tests/test_publisher.py +639 -0
- sealrun-0.5.0rc1/tests/test_publisher_export.py +619 -0
- sealrun-0.5.0rc1/tests/test_publisher_lock.py +258 -0
- sealrun-0.5.0rc1/tests/test_publisher_store.py +161 -0
- sealrun-0.5.0rc1/tests/test_publishing.py +115 -0
- sealrun-0.5.0rc1/tests/test_round2_regressions.py +973 -0
- sealrun-0.5.0rc1/tests/test_signer_cli.py +1115 -0
- sealrun-0.5.0rc1/tests/test_spv.py +481 -0
- sealrun-0.5.0rc1/tests/test_summarize_test_results.py +174 -0
- sealrun-0.5.0rc1/tests/test_tip_txid_option_a.py +331 -0
- sealrun-0.5.0rc1/tests/test_v2_anchor.py +1066 -0
- sealrun-0.5.0rc1/tests/test_v2_bootstrap.py +763 -0
- sealrun-0.5.0rc1/tests/test_v2_cache_signing.py +792 -0
- sealrun-0.5.0rc1/tests/test_v2_checkpoint_seq.py +41 -0
- sealrun-0.5.0rc1/tests/test_v2_error_handling.py +220 -0
- sealrun-0.5.0rc1/tests/test_v2_executable.py +689 -0
- sealrun-0.5.0rc1/tests/test_v2_journal.py +715 -0
- sealrun-0.5.0rc1/tests/test_v2_mode.py +746 -0
- sealrun-0.5.0rc1/tests/test_v2_rollback.py +931 -0
- sealrun-0.5.0rc1/tests/test_v2_run_state.py +415 -0
- sealrun-0.5.0rc1/tests/test_v2_signals.py +849 -0
sealrun-0.5.0rc1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rob Ganon
|
|
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.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sealrun
|
|
3
|
+
Version: 0.5.0rc1
|
|
4
|
+
Summary: Local AI artifact verification and tamper-evident audit prototype
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Provides-Extra: test
|
|
8
|
+
Requires-Dist: pytest>=8.0; extra == "test"
|
|
9
|
+
Dynamic: license-file
|
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# BSV AI Security
|
|
2
|
+
|
|
3
|
+
**Prove what your AI actually ran.**
|
|
4
|
+
|
|
5
|
+
> Note: the package and CLI were formerly named `aiguard`; renamed to
|
|
6
|
+
> `sealrun` on 2026-10-19 to avoid a collision with an unrelated product
|
|
7
|
+
> of the same name. The on-chain `AIGUARD1` payload magic is retained
|
|
8
|
+
> for anchor-chain continuity.
|
|
9
|
+
|
|
10
|
+
AI systems run as black boxes: you cannot prove *which* model and
|
|
11
|
+
configuration produced an output, or that the audit log describing it was
|
|
12
|
+
not rewritten afterwards. When an auditor, a regulator, or a customer
|
|
13
|
+
asks "show me exactly what ran," most teams have only their word.
|
|
14
|
+
|
|
15
|
+
This project gives you the evidence.
|
|
16
|
+
|
|
17
|
+
> **For the non-technical reader.** Think of it as a tamper-proof logbook
|
|
18
|
+
> for your AI. Before a model runs, the tool records a fingerprint of
|
|
19
|
+
> everything about to be used — which model, which data, which settings.
|
|
20
|
+
> After it runs, every security event goes into a chained record, where
|
|
21
|
+
> editing any earlier entry breaks the chain for everything after it. If
|
|
22
|
+
> an auditor or regulator ever asks "prove this is what ran," you show
|
|
23
|
+
> them the logbook. And if you anchor the fingerprints to a public
|
|
24
|
+
> ledger, even the logbook itself can never be quietly rewritten.
|
|
25
|
+
|
|
26
|
+
## See it work in 2 minutes
|
|
27
|
+
|
|
28
|
+
Watch the 19-second demo: [SealRun — verify an AI run before it starts, prove it afterwards](https://youtu.be/6z6a17UsD4g) — three tamper attempts, all caught.
|
|
29
|
+
|
|
30
|
+
SealRun proves what your AI actually ran — not whether it behaved well,
|
|
31
|
+
and not whether its outputs were true. Try it, then try breaking it:
|
|
32
|
+
|
|
33
|
+
1. Clone the repo and `pip install -e .` (no PyPI package or one-command
|
|
34
|
+
install yet — stated, not hidden).
|
|
35
|
+
2. Follow the worked example in
|
|
36
|
+
[`docs/using-sealrun.md`](docs/using-sealrun.md): `sealrun keygen`,
|
|
37
|
+
`manifest-create`, `manifest-sign`, `verify`, `launch`.
|
|
38
|
+
3. Break it: change `temperature` 0.2 → 0.9 in config.json and launch
|
|
39
|
+
again → `ERROR: artifact integrity mismatch: config.json`, exit code
|
|
40
|
+
1, the AI never starts. Then edit one word in `state/audit.jsonl`
|
|
41
|
+
and run `sealrun audit-verify` →
|
|
42
|
+
`ERROR: audit event hash mismatch at sequence 2`.
|
|
43
|
+
|
|
44
|
+
That is the whole claim, shown rather than asserted: a changed file stops
|
|
45
|
+
the run, and edited history is detectable.
|
|
46
|
+
|
|
47
|
+
## Who this is for, and who should wait
|
|
48
|
+
|
|
49
|
+
- For: anyone who runs AI on a machine they control — AI/ML and DevOps
|
|
50
|
+
teams who get asked "prove what ran," plus solo developers,
|
|
51
|
+
researchers, and hobbyists running a local model, experiment, or
|
|
52
|
+
script, and auditors, regulators, and customers who need checkable
|
|
53
|
+
evidence rather than a team's word.
|
|
54
|
+
- Maintained by: Rob Ganon.
|
|
55
|
+
- Wait if: you need an independently reviewed, beta-or-better tool today.
|
|
56
|
+
This is a research preview, not beta, not 1.0. The v2 launch flow hasn't
|
|
57
|
+
had an independent review yet, and mainnet anchoring is gated.
|
|
58
|
+
- When: no beta/1.0 date is promised.
|
|
59
|
+
- Where it runs / where evidence lives: Linux, on the machine running
|
|
60
|
+
the AI, stdlib-only offline core; manifest and journal are files you
|
|
61
|
+
hold locally; anchors (when used) are public on Teratestnet. A public
|
|
62
|
+
anchor is a checkpoint outside the machine's reach: even if someone
|
|
63
|
+
with full access rewrites the whole local journal, it will no longer
|
|
64
|
+
match the anchored fingerprint. Anchoring adds proof that holds up
|
|
65
|
+
against your own administrators, without publishing your data: only
|
|
66
|
+
hashes and sequence numbers go on-chain, never event contents, prompts,
|
|
67
|
+
model data, or keys — though anchor timing does reveal when you anchor.
|
|
68
|
+
- Where to get help: public GitHub issues for general feedback; private
|
|
69
|
+
vulnerability reporting only for security findings, under the standard
|
|
70
|
+
model adopted Oct 31. There is no community channel or forum — stated,
|
|
71
|
+
not implied.
|
|
72
|
+
- Where it does not reach: closed cloud agents or vendor infrastructure
|
|
73
|
+
you do not control; verification on an already-compromised host proves
|
|
74
|
+
nothing.
|
|
75
|
+
|
|
76
|
+
## Why use this
|
|
77
|
+
|
|
78
|
+
- **Prove what ran, not what was supposed to run.** A signed manifest
|
|
79
|
+
pins the exact model, code, data, and config bytes for a release.
|
|
80
|
+
Verification checks the signature *before* launch, so a swapped,
|
|
81
|
+
stale, or tampered artifact fails instead of running.
|
|
82
|
+
- **A tamper-evident record of what happened.** Every security event
|
|
83
|
+
goes into a hash-chained audit journal. Editing an earlier entry
|
|
84
|
+
breaks the chain, so rewriting history is detectable.
|
|
85
|
+
- **Rollback protection.** Monotonic release sequences reject
|
|
86
|
+
older legitimately-signed releases, so a system cannot be quietly
|
|
87
|
+
rolled back to a vulnerable version.
|
|
88
|
+
- **Evidence your auditors already ask for.** The journal and
|
|
89
|
+
manifests map directly onto what compliance requires: logging of
|
|
90
|
+
AI system activity (EU AI Act), change and access evidence
|
|
91
|
+
(SOC 2), and a reproducible record for incident forensics.
|
|
92
|
+
- **No blockchain required to start.** The local trust core works
|
|
93
|
+
with zero blockchain. Anchoring (below) is an optional upgrade
|
|
94
|
+
for when you need proof that holds up against your own
|
|
95
|
+
administrators — not a prerequisite for using the tool.
|
|
96
|
+
|
|
97
|
+
**What this is not.** It does not solve prompt injection, model
|
|
98
|
+
safety, data poisoning, adversarial ML, or privacy. It does not
|
|
99
|
+
prove that recorded events are truthful or complete — only that
|
|
100
|
+
they have not been altered after recording. It is the provenance
|
|
101
|
+
pillar of AI security: proving what ran, not whether the model
|
|
102
|
+
behaved well.
|
|
103
|
+
|
|
104
|
+
Status: test suite passing on main (see
|
|
105
|
+
[`REVIEW.md`](REVIEW.md) for the current count and evidence), plus
|
|
106
|
+
adversarial spot-checks on every feature. Independent security review
|
|
107
|
+
is still open
|
|
108
|
+
([issue #4](https://github.com/RobGanon/bsv-ai-security/issues/4)) —
|
|
109
|
+
we state that plainly because it matters.
|
|
110
|
+
|
|
111
|
+
New to the tool? [`docs/using-sealrun.md`](docs/using-sealrun.md)
|
|
112
|
+
walks the full flow — manifest, sign, launch, journal, proof — with
|
|
113
|
+
a worked example you can run in about ten minutes.
|
|
114
|
+
|
|
115
|
+
## What it saves you in money
|
|
116
|
+
|
|
117
|
+
No quantified case study exists yet — we will not invent savings
|
|
118
|
+
percentages. The mechanisms:
|
|
119
|
+
|
|
120
|
+
- **Audit and compliance preparation.** Evidence is preassembled
|
|
121
|
+
(signed manifests + chained journal) instead of reconstructed
|
|
122
|
+
after the fact.
|
|
123
|
+
- **Incident forensics.** Identify exactly which release produced
|
|
124
|
+
an output, instead of guessing across deployments.
|
|
125
|
+
- **Prevented bad runs.** A wrong, stale, or tampered artifact is
|
|
126
|
+
caught before launch, not after it burns a training or
|
|
127
|
+
deployment run.
|
|
128
|
+
- **Reproduce instead of retrain.** Hashes identify exactly what
|
|
129
|
+
changed, so unchanged inputs are not retrained.
|
|
130
|
+
- **Scoped legal retraining.** If data is disputed, retraining is
|
|
131
|
+
limited to the runs that actually used it.
|
|
132
|
+
- **Cheaper disputes.** Independently checkable evidence replaces
|
|
133
|
+
"trust us."
|
|
134
|
+
|
|
135
|
+
Next step: a pilot with one AI team measuring audit-prep hours
|
|
136
|
+
before and after adoption.
|
|
137
|
+
|
|
138
|
+
## How anchoring works
|
|
139
|
+
|
|
140
|
+
The local journal proves *order* and detects tampering — but an
|
|
141
|
+
administrator with full access could rewrite the whole journal
|
|
142
|
+
from scratch. Anchoring closes that hole: periodic journal heads
|
|
143
|
+
and rollback checkpoints are committed to a public blockchain,
|
|
144
|
+
so anyone holding the journal, the anchor transactions, and block
|
|
145
|
+
headers can verify history was never rewritten, even against the
|
|
146
|
+
local administrator.
|
|
147
|
+
|
|
148
|
+
The current anchor backend is BSV, chosen for cost and cadence:
|
|
149
|
+
anchors are small and frequent (on release acceptance plus
|
|
150
|
+
scheduled checkpoints), and BSV's low fees and native on-chain
|
|
151
|
+
data make that practical. Verification is SPV-style — verifiers
|
|
152
|
+
check headers, not a full node.
|
|
153
|
+
|
|
154
|
+
The anchor chain runs on Teratestnet, BSV's test network, using
|
|
155
|
+
SPV plus the WhatsOnChain testnet API. SealRun does not run a node
|
|
156
|
+
and does not run Teranode; BSV scaling is powered by Teranode.
|
|
157
|
+
|
|
158
|
+
Honest tradeoff, both ways: BTC has substantially deeper
|
|
159
|
+
proof-of-work security today. BSV's case is cost, frequency, and
|
|
160
|
+
data fit, not maximum settlement depth. That tradeoff could change
|
|
161
|
+
over time: BSV's mechanism is utility driving demand, demand
|
|
162
|
+
driving miner revenue, and miner revenue driving hashpower — a
|
|
163
|
+
mechanism, not a prediction that BSV overtakes BTC.
|
|
164
|
+
|
|
165
|
+
Why BSV fits this project, in engineering terms: the original
|
|
166
|
+
Bitcoin design was a peer-to-peer electronic cash system, with
|
|
167
|
+
payments made directly between parties without a financial
|
|
168
|
+
institution. BSV's goal aligns with that payment-system goal. The
|
|
169
|
+
project uses BSV for that reason — frequent, cheap,
|
|
170
|
+
data-carrying anchors — not as a claim about which chain "is"
|
|
171
|
+
Bitcoin.
|
|
172
|
+
|
|
173
|
+
Anchoring proves history integrity and existence, not
|
|
174
|
+
truthfulness or completeness of the journal.
|
|
175
|
+
|
|
176
|
+
**Current status:** the publisher and broadcaster are live on
|
|
177
|
+
Teratestnet. Three anchors are confirmed on-chain: anchor #1
|
|
178
|
+
(`4111b7cf9d42624be75aa78f5031caaebe4e836665b95fbcdbadbb086b2bf029`,
|
|
179
|
+
block 36722), anchor #2
|
|
180
|
+
(`d8407bb7a60f23aadcf021e9cb0098c6ae362a519aa04cbd8536265519c09230`,
|
|
181
|
+
block 36723), and anchor #3
|
|
182
|
+
(`e3a95a6f1f65651949f8fc6ef1ce22292058502cc6a94aef0fb6a5143ffd28cb`,
|
|
183
|
+
block 37163) — anchor #3 was signed by a human through the
|
|
184
|
+
offline-signing ceremony below, not by the publisher. See
|
|
185
|
+
`docs/anchoring-protocol.md` for the verifier
|
|
186
|
+
procedure and what anchoring does and does not prove. Anchor signing
|
|
187
|
+
goes through the offline-signing ceremony — the publisher exports an
|
|
188
|
+
unsigned tx, a human-side signer signs it, and the publisher verifies
|
|
189
|
+
and broadcasts it — documented in
|
|
190
|
+
`docs/offline-signing-handoff.md`.
|
|
191
|
+
|
|
192
|
+
## Training-data provenance
|
|
193
|
+
|
|
194
|
+
The same mechanism works for training data: record a signed
|
|
195
|
+
dataset manifest *before* training, and the manifest + journal +
|
|
196
|
+
anchor prove what was in the training set and when it was
|
|
197
|
+
recorded. A creator can likewise hash and timestamp their work
|
|
198
|
+
before it is ever used.
|
|
199
|
+
|
|
200
|
+
Hard limits: this proves what was recorded. It does not stop
|
|
201
|
+
scraping, enforce consent or licenses, or prove an omitted item
|
|
202
|
+
was not secretly used. It helps parties who adopt it *before*
|
|
203
|
+
the dispute — it cannot retroactively prove an unrecorded run.
|
|
204
|
+
|
|
205
|
+
## What makes this different
|
|
206
|
+
|
|
207
|
+
Hash-chained logs, signed artifacts, and timestamping all have
|
|
208
|
+
real precedents — Sigstore/Rekor, in-toto/SLSA, OpenTimestamps,
|
|
209
|
+
Certificate Transparency, CloudTrail, systemd journal sealing.
|
|
210
|
+
No single product combines all of this specifically for AI
|
|
211
|
+
operations: signed manifests pinning model, code, data, and
|
|
212
|
+
config bytes; TOCTOU-resistant verified file-descriptor handoff;
|
|
213
|
+
journal-derived rollback protection; manifest-bound acceptance;
|
|
214
|
+
and chain-continuous anchors.
|
|
215
|
+
|
|
216
|
+
Contributions welcome — especially security review. If you find something,
|
|
217
|
+
open an issue.
|
|
218
|
+
|
|
219
|
+
---
|
|
220
|
+
|
|
221
|
+
## Phase 1: Linux trust core (v0.4.0)
|
|
222
|
+
|
|
223
|
+
This prototype verifies a signed manifest of local AI artifacts and records local
|
|
224
|
+
security events in a hash-chained JSONL audit journal. It is intentionally
|
|
225
|
+
limited in scope:
|
|
226
|
+
|
|
227
|
+
- SHA-256 identifies artifact bytes; secp256k1 ECDSA verifies the release manifest.
|
|
228
|
+
- The audit journal is append-only under normal operation and hash-chained so
|
|
229
|
+
that any modification of earlier events is detectable.
|
|
230
|
+
- The manifest verifier does not itself sandbox a model. `sealrun launch`
|
|
231
|
+
pins the verified bytes across exec, but containment is out of scope.
|
|
232
|
+
- The manifest uses relative artifact paths and rejects path traversal/symlinks.
|
|
233
|
+
|
|
234
|
+
### Quick start
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
pip install -e .
|
|
238
|
+
|
|
239
|
+
# Generate a key pair (demo only — production keys must be offline / HSM).
|
|
240
|
+
sealrun keygen --private-key demo/private.wif --public-key demo/public.pub
|
|
241
|
+
|
|
242
|
+
# Create an unsigned manifest template, then sign it.
|
|
243
|
+
sealrun manifest-create \
|
|
244
|
+
--root demo/artifacts \
|
|
245
|
+
--artifact model.bin --artifact config.json \
|
|
246
|
+
--release-id demo-release-001 \
|
|
247
|
+
--release-seq 1 \
|
|
248
|
+
--output demo/manifest.json
|
|
249
|
+
|
|
250
|
+
sealrun manifest-sign \
|
|
251
|
+
--manifest demo/manifest.json \
|
|
252
|
+
--private-key demo/private.wif \
|
|
253
|
+
--output demo/manifest.signed.json
|
|
254
|
+
|
|
255
|
+
# Verify (paths relative to --root).
|
|
256
|
+
sealrun verify \
|
|
257
|
+
--root demo/artifacts \
|
|
258
|
+
--manifest demo/manifest.signed.json \
|
|
259
|
+
--public-key demo/public.pub
|
|
260
|
+
|
|
261
|
+
# Optional rollback protection: reject any manifest older than sequence 1.
|
|
262
|
+
sealrun verify \
|
|
263
|
+
--root demo/artifacts \
|
|
264
|
+
--manifest demo/manifest.signed.json \
|
|
265
|
+
--public-key demo/public.pub \
|
|
266
|
+
--min-release-seq 1
|
|
267
|
+
|
|
268
|
+
# Launch against the verified handles instead of reopening paths.
|
|
269
|
+
sealrun launch \
|
|
270
|
+
--root demo/artifacts \
|
|
271
|
+
--manifest demo/manifest.signed.json \
|
|
272
|
+
--public-key demo/public.pub \
|
|
273
|
+
-- /bin/sh -c 'cat "$SEALRUN_ARTIFACT_MODEL_BIN"'
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Launching with verified handles
|
|
277
|
+
|
|
278
|
+
`sealrun verify` proves the manifest, then exits — a caller that launches
|
|
279
|
+
the model *by path* reopens the artifacts, leaving a window for a path
|
|
280
|
+
swap between check and use. `sealrun launch` closes that window: it runs
|
|
281
|
+
the same verification, keeps the verified descriptors open, and hands
|
|
282
|
+
them to the command via `SEALRUN_ARTIFACT_*` environment variables
|
|
283
|
+
pointing at `/proc/self/fd/N`.
|
|
284
|
+
|
|
285
|
+
- `--seal` copies each artifact into a sealed `memfd` first, so the child
|
|
286
|
+
reads a frozen snapshot even if a writer mutates the original (costs a
|
|
287
|
+
copy in RAM; opt-in).
|
|
288
|
+
- `--uid`/`--gid` drop privilege before exec, so a launcher started as
|
|
289
|
+
root can make the model run unprivileged. If the drop is not permitted
|
|
290
|
+
the command does not run; `--uid` alone uses the target user's primary
|
|
291
|
+
group and supplementary groups are cleared.
|
|
292
|
+
- The launcher pins *what bytes are launched*; it does not sandbox the
|
|
293
|
+
child. See [`docs/launcher.md`](docs/launcher.md) for the contract and
|
|
294
|
+
the residual limits. For the strongest launch configuration, see
|
|
295
|
+
[`docs/high-assurance-profile.md`](docs/high-assurance-profile.md).
|
|
296
|
+
|
|
297
|
+
## Audit journal
|
|
298
|
+
|
|
299
|
+
```bash
|
|
300
|
+
sealrun audit-append --journal demo/audit.jsonl --event-type "verification" --detail "demo check"
|
|
301
|
+
sealrun audit-verify --journal demo/audit.jsonl
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
The journal is hash-chained but not protected against an administrator who can
|
|
305
|
+
rewrite the entire file. Anchor periodic roots externally (on BSV) and retain
|
|
306
|
+
inclusion proofs/checkpoints separately — see "How anchoring works" above and
|
|
307
|
+
`docs/anchoring-protocol.md`.
|
|
308
|
+
|
|
309
|
+
On Unix platforms the append path takes an exclusive advisory lock
|
|
310
|
+
(`fcntl.flock`) across the verify-then-write critical section. Concurrent
|
|
311
|
+
writers are serialised; platforms without `fcntl` fall back to the
|
|
312
|
+
single-writer assumption.
|
|
313
|
+
|
|
314
|
+
Event `detail` is limited to 4096 UTF-8 bytes and the journal is limited to
|
|
315
|
+
1 000 000 events. Exceeding either limit raises `VerificationError`.
|
|
316
|
+
All stored hashes are normalised to lowercase; mixed-case input is accepted
|
|
317
|
+
and compared case-insensitively.
|
|
318
|
+
|
|
319
|
+
## Tests
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
pytest -q
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
Tests are not claimed to have passed until you run them in your environment.
|
|
326
|
+
Reviewing? See `docs/reviewer-brief.md` for a 15-minute orientation and
|
|
327
|
+
`docs/reviewer-quickstart.md` for the 5-minute path.
|
|
328
|
+
|
|
329
|
+
## Manifest format
|
|
330
|
+
|
|
331
|
+
The signed payload is canonical JSON (UTF-8, sorted keys, compact separators).
|
|
332
|
+
The signature is deterministic secp256k1 ECDSA (RFC 6979, low-S normalized,
|
|
333
|
+
DER-encoded) over SHA-256 of the exact canonical payload bytes, encoded as
|
|
334
|
+
base64. Example:
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"schema": "sealrun-manifest-v1",
|
|
339
|
+
"release_id": "demo-release-001",
|
|
340
|
+
"release_seq": 1,
|
|
341
|
+
"artifacts": [
|
|
342
|
+
{
|
|
343
|
+
"path": "artifacts/model.bin",
|
|
344
|
+
"sha256": "REPLACE_WITH_64_HEX_CHARACTERS",
|
|
345
|
+
"size": 123
|
|
346
|
+
}
|
|
347
|
+
]
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
The signed envelope generated by `manifest-sign` looks like:
|
|
352
|
+
|
|
353
|
+
```json
|
|
354
|
+
{
|
|
355
|
+
"payload": { "...": "..." },
|
|
356
|
+
"signature": "BASE64_DER_SIGNATURE"
|
|
357
|
+
}
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
The trusted public key is supplied out of band. A public key shipped alongside an
|
|
361
|
+
untrusted manifest is not a trust anchor.
|
|
362
|
+
|
|
363
|
+
## Rollback protection
|
|
364
|
+
|
|
365
|
+
Each manifest carries a monotonic `release_seq` integer inside the signed
|
|
366
|
+
payload. `verify --min-release-seq N` rejects any manifest older than N,
|
|
367
|
+
which defeats rollback attacks (an older legitimately-signed manifest
|
|
368
|
+
verifying cleanly). The mechanism is implemented; the *policy* — where the
|
|
369
|
+
caller obtains and stores the highest accepted sequence — is left to the
|
|
370
|
+
integrating system (on-chain anchors checkpoint it; see
|
|
371
|
+
`docs/anchoring-protocol.md`).
|
|
372
|
+
|
|
373
|
+
## Phase 2: BSV anchoring (implemented)
|
|
374
|
+
|
|
375
|
+
`docs/anchoring-protocol.md` specifies how the audit journal and rollback
|
|
376
|
+
checkpoint get anchored to BSV for independent verifiability — including the
|
|
377
|
+
exact 84-byte OP_RETURN payload layout, the on-chain anchor chaining via
|
|
378
|
+
`prev_txid`, the independent verifier procedure, and an explicit list of
|
|
379
|
+
what anchoring does and does not prove. The publisher, broadcaster, and
|
|
380
|
+
verifiers (SPV inclusion, BUMP, BEEF, header-chain, anchor-input
|
|
381
|
+
signatures) are implemented and tested.
|
|
382
|
+
|
|
383
|
+
## Pilot program
|
|
384
|
+
|
|
385
|
+
We are looking for one AI team to run a 30-day pilot on one real
|
|
386
|
+
pipeline. Details: [`docs/pilot-brief.md`](docs/pilot-brief.md).
|
|
387
|
+
|
|
388
|
+
## Roadmap (high level)
|
|
389
|
+
|
|
390
|
+
1. Independent review of Phase 1 (requested — see `REVIEW.md`).
|
|
391
|
+
2. ~~Implement Phase 2 payload creation + local verification~~ — done.
|
|
392
|
+
3. ~~Implement publishing interfaces with explicit network selection
|
|
393
|
+
(testnet default; mainnet behind separate confirmation)~~ — done.
|
|
394
|
+
4. ~~Independent SPV / header-chain verification~~ — done.
|
|
395
|
+
5. ~~Migrate manifest signing from Ed25519 to secp256k1~~ — done.
|
|
396
|
+
6. ~~Privileged launcher that consumes verified artifact handles~~ — done
|
|
397
|
+
(`sealrun launch`; see `docs/launcher.md`).
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "sealrun"
|
|
7
|
+
version = "0.5.0rc1"
|
|
8
|
+
description = "Local AI artifact verification and tamper-evident audit prototype"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = []
|
|
11
|
+
|
|
12
|
+
[project.optional-dependencies]
|
|
13
|
+
test = ["pytest>=8.0"]
|
|
14
|
+
|
|
15
|
+
[project.scripts]
|
|
16
|
+
sealrun = "sealrun.cli:main"
|
|
17
|
+
|
|
18
|
+
[tool.pytest.ini_options]
|
|
19
|
+
testpaths = ["tests"]
|