gargoyle-receipts 0.14.0.dev0__tar.gz → 0.14.1.dev0__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 (83) hide show
  1. {gargoyle_receipts-0.14.0.dev0/gargoyle_receipts.egg-info → gargoyle_receipts-0.14.1.dev0}/PKG-INFO +2 -2
  2. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/README.md +1 -1
  3. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/cli.py +6 -0
  4. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/witness.py +5 -0
  5. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0/gargoyle_receipts.egg-info}/PKG-INFO +2 -2
  6. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/pyproject.toml +1 -1
  7. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_witness.py +14 -0
  8. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/LICENSE +0 -0
  9. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/NOTICE +0 -0
  10. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/__init__.py +0 -0
  11. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/adapters.py +0 -0
  12. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/approval.py +0 -0
  13. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/approver_cli.py +0 -0
  14. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/approver_trust.py +0 -0
  15. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/approvers.py +0 -0
  16. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/consumer.py +0 -0
  17. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/entra_login.py +0 -0
  18. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/envelope.py +0 -0
  19. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/evidence.py +0 -0
  20. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/execution.py +0 -0
  21. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/fs_server.py +0 -0
  22. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/holdstore.py +0 -0
  23. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/identity.py +0 -0
  24. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/issuer.py +0 -0
  25. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/issuer_service.py +0 -0
  26. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/jws.py +0 -0
  27. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/key_record_source.py +0 -0
  28. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/mcp_server.py +0 -0
  29. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/notify.py +0 -0
  30. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/opa.py +0 -0
  31. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/pending_store.py +0 -0
  32. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/plans.py +0 -0
  33. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/policy.py +0 -0
  34. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/published_record_source.py +0 -0
  35. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/reconcile.py +0 -0
  36. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/remote.py +0 -0
  37. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/replay_cache.py +0 -0
  38. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/revert.py +0 -0
  39. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/rules.py +0 -0
  40. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/specs/graph-reference.json +0 -0
  41. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/state.py +0 -0
  42. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/static/approve.html +0 -0
  43. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/static/approve.js +0 -0
  44. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle/verifier.py +0 -0
  45. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle_receipts.egg-info/SOURCES.txt +0 -0
  46. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle_receipts.egg-info/dependency_links.txt +0 -0
  47. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle_receipts.egg-info/entry_points.txt +0 -0
  48. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle_receipts.egg-info/requires.txt +0 -0
  49. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/gargoyle_receipts.egg-info/top_level.txt +0 -0
  50. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/setup.cfg +0 -0
  51. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_annotations.py +0 -0
  52. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_approver_cli.py +0 -0
  53. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_approvers.py +0 -0
  54. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_canonical.py +0 -0
  55. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_cli.py +0 -0
  56. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_console_js.py +0 -0
  57. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_consumer.py +0 -0
  58. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_entra_identity.py +0 -0
  59. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_entra_login.py +0 -0
  60. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_evidence.py +0 -0
  61. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_execution.py +0 -0
  62. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_fs_server.py +0 -0
  63. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_graph.py +0 -0
  64. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_historical.py +0 -0
  65. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_identity.py +0 -0
  66. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_issuer_service.py +0 -0
  67. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_jws.py +0 -0
  68. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_mcp_proxy.py +0 -0
  69. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_mcp_self_issue.py +0 -0
  70. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_mcp_server.py +0 -0
  71. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_notify.py +0 -0
  72. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_opa.py +0 -0
  73. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_plans.py +0 -0
  74. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_policy.py +0 -0
  75. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_published_record.py +0 -0
  76. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_remote.py +0 -0
  77. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_revert.py +0 -0
  78. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_rules.py +0 -0
  79. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_state.py +0 -0
  80. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_stdio_encoding.py +0 -0
  81. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_threshold.py +0 -0
  82. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_typescript_conformance.py +0 -0
  83. {gargoyle_receipts-0.14.0.dev0 → gargoyle_receipts-0.14.1.dev0}/tests/test_wire_spec.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gargoyle-receipts
3
- Version: 0.14.0.dev0
3
+ Version: 0.14.1.dev0
4
4
  Summary: Signed, single-use, argument-bound receipts and human-approval holds for agent tool calls.
5
5
  Author: Justin LaPorte
6
6
  License-Expression: Apache-2.0
@@ -59,7 +59,7 @@ your MCP server and lets through only what both agreed to.
59
59
 
60
60
  [![PyPI](https://img.shields.io/pypi/v/gargoyle-receipts)](https://pypi.org/project/gargoyle-receipts/)
61
61
 
62
- Status: pre-release (`0.14.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
62
+ Status: pre-release (`0.14.1.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
63
63
  still change before the first release; it is specified in [SPEC.md](SPEC.md).
64
64
 
65
65
  ## What a receipt gives you
@@ -21,7 +21,7 @@ your MCP server and lets through only what both agreed to.
21
21
 
22
22
  [![PyPI](https://img.shields.io/pypi/v/gargoyle-receipts)](https://pypi.org/project/gargoyle-receipts/)
23
23
 
24
- Status: pre-release (`0.14.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
24
+ Status: pre-release (`0.14.1.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
25
25
  still change before the first release; it is specified in [SPEC.md](SPEC.md).
26
26
 
27
27
  ## What a receipt gives you
@@ -361,6 +361,12 @@ def cmd_audit(args) -> int:
361
361
  % (v["count"], v["honored"], v["refused"], failed, v["reason"], v["tail_sha256"][:16]))
362
362
  rc = 0 if v["accepted"] else 1
363
363
  entries = read_log(args.log)
364
+ if args.witness and not Path(args.witness).exists():
365
+ print("witness file not found: %s (copy the issuer's witness.jsonl here first)" % args.witness, file=sys.stderr)
366
+ return 2
367
+ if args.check_tree and not Path(args.check_tree).is_dir():
368
+ print("not a directory: %s" % args.check_tree, file=sys.stderr)
369
+ return 2
364
370
  if args.witness:
365
371
  # The issuer's signed record: the client's evidence must agree with it.
366
372
  from gargoyle.reconcile import reconcile
@@ -63,6 +63,11 @@ class WitnessLog:
63
63
  e = json.loads(line)
64
64
  self.entries.append(e)
65
65
  self._seq, self._tail = int(e["seq"]), e["entry_sha256"]
66
+ elif self.path is not None:
67
+ # Exists from the first start, so an operator can copy it before
68
+ # the first decision and a monitor can see it is in place.
69
+ self.path.parent.mkdir(parents=True, exist_ok=True)
70
+ self.path.touch()
66
71
 
67
72
  def record(self, event: str, **fields: Any) -> Dict[str, Any]:
68
73
  with self._lock:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gargoyle-receipts
3
- Version: 0.14.0.dev0
3
+ Version: 0.14.1.dev0
4
4
  Summary: Signed, single-use, argument-bound receipts and human-approval holds for agent tool calls.
5
5
  Author: Justin LaPorte
6
6
  License-Expression: Apache-2.0
@@ -59,7 +59,7 @@ your MCP server and lets through only what both agreed to.
59
59
 
60
60
  [![PyPI](https://img.shields.io/pypi/v/gargoyle-receipts)](https://pypi.org/project/gargoyle-receipts/)
61
61
 
62
- Status: pre-release (`0.14.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
62
+ Status: pre-release (`0.14.1.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
63
63
  still change before the first release; it is specified in [SPEC.md](SPEC.md).
64
64
 
65
65
  ## What a receipt gives you
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "gargoyle-receipts"
7
- version = "0.14.0.dev0"
7
+ version = "0.14.1.dev0"
8
8
  description = "Signed, single-use, argument-bound receipts and human-approval holds for agent tool calls."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -149,3 +149,17 @@ def test_audit_command_reports_reconciliation_and_tree(tmp_path, capsys):
149
149
  (root / "n.md").write_text("tampered", encoding="utf-8")
150
150
  assert main(["audit", "--log", str(tmp_path / "audit.jsonl"), "--out", str(out), "--check-tree", str(root)]) == 1
151
151
  assert "CHANGED_OUTSIDE_GATE" in capsys.readouterr().out
152
+
153
+
154
+ def test_audit_names_a_missing_witness_or_folder_plainly(tmp_path, capsys):
155
+ from gargoyle.cli import main
156
+ log = tmp_path / "audit.jsonl"; log.write_text("")
157
+ out = tmp_path / "deploy"; out.mkdir()
158
+ (out / "public-keys.json").write_text(json.dumps({"issuer": {}, "executor": {}, "approver": {}}))
159
+ assert main(["audit", "--log", str(log), "--out", str(out), "--witness", str(tmp_path / "nope.jsonl")]) == 2
160
+ assert "witness file not found" in capsys.readouterr().err
161
+ assert main(["audit", "--log", str(log), "--out", str(out), "--check-tree", str(tmp_path / "nodir")]) == 2
162
+ assert "not a directory" in capsys.readouterr().err
163
+ # The issuer creates the witness file at start, before any decision.
164
+ w = WitnessLog(str(tmp_path / "fresh" / "witness.jsonl"), issuer, "issuer-1")
165
+ assert (tmp_path / "fresh" / "witness.jsonl").exists() and w.entries == []