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.
Files changed (35) hide show
  1. {vitnify-0.2.3/src/vitnify.egg-info → vitnify-0.2.4}/PKG-INFO +1 -1
  2. {vitnify-0.2.3 → vitnify-0.2.4}/pyproject.toml +1 -1
  3. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/certificate.py +7 -0
  4. {vitnify-0.2.3 → vitnify-0.2.4/src/vitnify.egg-info}/PKG-INFO +1 -1
  5. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_verify_hardening.py +25 -0
  6. {vitnify-0.2.3 → vitnify-0.2.4}/LICENSE +0 -0
  7. {vitnify-0.2.3 → vitnify-0.2.4}/NOTICE +0 -0
  8. {vitnify-0.2.3 → vitnify-0.2.4}/README.md +0 -0
  9. {vitnify-0.2.3 → vitnify-0.2.4}/setup.cfg +0 -0
  10. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/__init__.py +0 -0
  11. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/__init__.py +0 -0
  12. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/pck/__init__.py +0 -0
  13. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/_vendor/pck/cas.py +0 -0
  14. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/capability.py +0 -0
  15. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/deterministic_llm.py +0 -0
  16. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/engine.py +0 -0
  17. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/events.py +0 -0
  18. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/langgraph_adapter.py +0 -0
  19. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/mcp_adapter.py +0 -0
  20. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/react.py +0 -0
  21. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/replayer.py +0 -0
  22. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify/viewer.py +0 -0
  23. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/SOURCES.txt +0 -0
  24. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/dependency_links.txt +0 -0
  25. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/requires.txt +0 -0
  26. {vitnify-0.2.3 → vitnify-0.2.4}/src/vitnify.egg-info/top_level.txt +0 -0
  27. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_adapters.py +0 -0
  28. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_attack_matrix.py +0 -0
  29. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_capability.py +0 -0
  30. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_certificate.py +0 -0
  31. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_ed25519.py +0 -0
  32. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_events.py +0 -0
  33. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_l2_recompute.py +0 -0
  34. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_receipt_v2.py +0 -0
  35. {vitnify-0.2.3 → vitnify-0.2.4}/tests/test_verification.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vitnify
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Execution receipts for AI agents: contain, deterministically reconstruct, and cryptographically certify a run.
5
5
  Author: vitnify
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "vitnify"
7
- version = "0.2.3"
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,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: vitnify
3
- Version: 0.2.3
3
+ Version: 0.2.4
4
4
  Summary: Execution receipts for AI agents: contain, deterministically reconstruct, and cryptographically certify a run.
5
5
  Author: vitnify
6
6
  License: Apache-2.0
@@ -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