audit-labs/evidence-seal

Tamper-evident seals and chain of custody for audit evidence.

clone: git clone https://gitbay.org/audit-labs/evidence-seal.git

de4792aac7adb09234c2a2247b7dc1216ff95b07

verified · cmc

author: Christian Cleberg <hello@cleberg.net> · 2026-08-07T02:13:39Z

Align install docs, expand threat model, add CI

- README install matches the site (direct-from-git one-liner); clone moved
  under Development
- Threat model states that a seal proves the package is unchanged, not that
  the collection faithfully represented the system at collection time
- Add ruff + pytest CI; drop a stale noqa directive
 .github/workflows/ci.yml | 26 ++++++++++++++++++++++++++
 README.md                | 21 ++++++++++++++++-----
 scripts/_local_tsa.py    |  2 +-
 3 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 0000000..affc03a
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,26 @@
+name: CI
+
+on:
+  push:
+  pull_request:
+
+jobs:
+  test:
+    runs-on: ubuntu-latest
+    strategy:
+      matrix:
+        python-version: ["3.10", "3.12"]
+    steps:
+      - uses: actions/checkout@v5
+      - name: Set up Python ${{ matrix.python-version }}
+        uses: actions/setup-python@v6
+        with:
+          python-version: ${{ matrix.python-version }}
+      - name: Install
+        run: |
+          python -m pip install --upgrade pip
+          pip install -e ".[dev]"
+      - name: Ruff
+        run: ruff check .
+      - name: Tests
+        run: pytest -q
diff --git a/README.md b/README.md
index d8f2a7e..5254278 100644
--- a/README.md
+++ b/README.md
@@ -27,12 +27,15 @@ timestamping needs `asn1crypto` (`evidence-seal[timestamp]`).
 ## Install
 
 ```bash
-git clone https://github.com/audit-labs/evidence-seal
-cd evidence-seal
-python -m venv .venv && source .venv/bin/activate
-pip install -e ".[sign,timestamp]"   # or drop the extras for the zero-dependency core
+# Core is pure standard library; extras add signing + timestamping.
+pip install "evidence-seal[sign,timestamp] @ git+https://github.com/audit-labs/evidence-seal"
+
+# Or, for the zero-dependency core, drop the extras:
+pip install "evidence-seal @ git+https://github.com/audit-labs/evidence-seal"
 ```
 
+To hack on it from a clone instead, see [Development](#development).
+
 ## Usage
 
 ```bash
@@ -160,7 +163,15 @@ untimestamped* manifest can be regenerated by anyone with the files, and its
 guarantee, **sign** the manifest (retain the public key out of band) and
 **timestamp** it with a trusted TSA.
 
-Two limits to be honest about:
+**What a seal does not prove.** A seal proves the *package* is unchanged since it
+was sealed — nothing more. It says nothing about whether the collection faithfully
+represented the system at collection time: whether the right scope was captured,
+whether a query was complete, or whether the evidence was gathered from the
+production system at all. That is the question an auditor actually asks, and it is
+answered by collection controls and re-performance, not by this tool. Seal the
+evidence; don't mistake an intact seal for a trustworthy collection.
+
+Further limits to be honest about:
 
 - **`timestamp verify` checks the binding; `--tsa-cert` adds signature
   verification but not chain-of-trust.** Without a cert, verification proves the
diff --git a/scripts/_local_tsa.py b/scripts/_local_tsa.py
index 9df7bea..1819cd8 100644
--- a/scripts/_local_tsa.py
+++ b/scripts/_local_tsa.py
@@ -17,7 +17,7 @@ _REPO = _HERE.parent.parent
 sys.path.insert(0, str(_REPO / "tests"))
 sys.path.insert(0, str(_REPO))
 
-from test_timestamp import issue_signed_token  # noqa: E402
+from test_timestamp import issue_signed_token
 
 
 def main() -> None: