vitnify 0.2.3__tar.gz → 0.2.4__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.
- {vitnify-0.2.3/src/vitnify.egg-info → vitnify-0.2.4}/PKG-INFO +1 -1
- {vitnify-0.2.3 → vitnify-0.2.4}/pyproject.toml +1 -1
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/certificate.py +7 -0
- {vitnify-0.2.3 → vitnify-0.2.4/src/vitnify.egg-info}/PKG-INFO +1 -1
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_verify_hardening.py +25 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/LICENSE +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/NOTICE +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/README.md +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/setup.cfg +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/__init__.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/__init__.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/pck/__init__.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/pck/cas.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/capability.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/deterministic_llm.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/engine.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/events.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/langgraph_adapter.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/mcp_adapter.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/react.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/replayer.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/viewer.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/SOURCES.txt +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/dependency_links.txt +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/requires.txt +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/top_level.txt +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_adapters.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_attack_matrix.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_capability.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_certificate.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_ed25519.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_events.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_l2_recompute.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_receipt_v2.py +0 -0
- {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_verification.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "vitnify"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.4"
|
|
8
8
|
description = "Execution receipts for AI agents: contain, deterministically reconstruct, and cryptographically certify a run."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -158,8 +158,15 @@ def verify_certificate(cert: ExecutionCertificate, log: EventLog, key: bytes | N
|
|
|
158
158
|
needs the model weights.)
|
|
159
159
|
"""
|
|
160
160
|
cas = MerkleCAS(log.chunks())
|
|
161
|
+
# Every event kind must be recognised. The semantic checks below filter events
|
|
162
|
+
# by an EXACT kind match, so an unknown kind ("TOOL_CALL", "toolcall", ...) would
|
|
163
|
+
# slip past them silently -- the same self-declared-label class as an unknown
|
|
164
|
+
# sig_alg or an unknown decision string. Fail closed here so the whole class is
|
|
165
|
+
# gone: an unrecognised kind (or decision, or algorithm, or format) never verifies.
|
|
166
|
+
known_kinds = {k.value for k in Kind}
|
|
161
167
|
checks = {
|
|
162
168
|
"format": cert.v in SUPPORTED_FORMATS,
|
|
169
|
+
"kinds_known": all(e.kind in known_kinds for e in log.events),
|
|
163
170
|
"root_matches": cas.root == cert.event_root,
|
|
164
171
|
"head_matches": log.head() == cert.head_hash,
|
|
165
172
|
"count_matches": len(log) == cert.n_events,
|
|
@@ -95,3 +95,28 @@ def test_f11_containment_not_evaded_by_decision_string():
|
|
|
95
95
|
log = EventLog(); log.append(Kind.TOOL_CALL, {"tool": "send_email", "decision": "DENY"})
|
|
96
96
|
cert, _ = issue_certificate("prog", ["read_docs"], log, priv=priv)
|
|
97
97
|
assert verify_certificate(cert, log)["ok"] is True
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def test_f12_unknown_event_kind_is_rejected():
|
|
101
|
+
# F12: the semantic checks filter events by an exact kind match, so an unknown
|
|
102
|
+
# kind would slip past them. Fail closed -- any unrecognised kind invalidates the
|
|
103
|
+
# receipt. This closes the whole "self-declared label evades a filter" class:
|
|
104
|
+
# F1 (sig_alg), F11 (decision), F12 (kind) all now fail closed on unknown values.
|
|
105
|
+
priv, _ = gen_ed25519()
|
|
106
|
+
# an ungranted tool hidden under an unrecognised kind must not escape containment
|
|
107
|
+
log = EventLog(); log.append("TOOL_CALL", {"tool": "wire_transfer", "decision": "ALLOW", "result": "x"})
|
|
108
|
+
cert, _ = issue_certificate("prog", ["read_docs"], log, priv=priv)
|
|
109
|
+
r = verify_certificate(cert, log)
|
|
110
|
+
assert r["kinds_known"] is False and r["ok"] is False
|
|
111
|
+
# a model step hidden under an unrecognised kind must not verify either
|
|
112
|
+
log = EventLog(); log.append("LLM_CALL", {"prompt_hash": "p", "tokens": [1], "seed": 0, "model_digest": "d"})
|
|
113
|
+
cert, _ = issue_certificate("prog", [], log, priv=priv)
|
|
114
|
+
assert verify_certificate(cert, log)["ok"] is False
|
|
115
|
+
# every recognised kind still verifies
|
|
116
|
+
log = EventLog()
|
|
117
|
+
log.append(Kind.LLM_CALL, {"prompt_hash": "p", "tokens": [1], "seed": 0, "model_digest": "d"})
|
|
118
|
+
log.append(Kind.TOOL_CALL, {"tool": "read_docs", "decision": "ALLOW", "result": "r", "result_hash": "h"})
|
|
119
|
+
log.append(Kind.ENTROPY, {"source": "clock", "value": 1})
|
|
120
|
+
log.append(Kind.AGENT_STEP, {"state": "done"})
|
|
121
|
+
cert, _ = issue_certificate("prog", ["read_docs"], log, priv=priv)
|
|
122
|
+
assert verify_certificate(cert, log)["ok"] is True
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|