gargoyle-receipts 0.8.0.dev0__tar.gz → 0.8.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 (72) hide show
  1. {gargoyle_receipts-0.8.0.dev0/gargoyle_receipts.egg-info → gargoyle_receipts-0.8.1.dev0}/PKG-INFO +2 -2
  2. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/README.md +1 -1
  3. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/fs_server.py +8 -3
  4. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0/gargoyle_receipts.egg-info}/PKG-INFO +2 -2
  5. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/pyproject.toml +1 -1
  6. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_fs_server.py +11 -0
  7. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/LICENSE +0 -0
  8. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/NOTICE +0 -0
  9. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/__init__.py +0 -0
  10. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/approval.py +0 -0
  11. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/approver_cli.py +0 -0
  12. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/approver_trust.py +0 -0
  13. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/approvers.py +0 -0
  14. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/cli.py +0 -0
  15. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/consumer.py +0 -0
  16. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/entra_login.py +0 -0
  17. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/envelope.py +0 -0
  18. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/evidence.py +0 -0
  19. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/execution.py +0 -0
  20. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/identity.py +0 -0
  21. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/issuer.py +0 -0
  22. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/issuer_service.py +0 -0
  23. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/jws.py +0 -0
  24. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/key_record_source.py +0 -0
  25. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/mcp_server.py +0 -0
  26. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/notify.py +0 -0
  27. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/opa.py +0 -0
  28. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/pending_store.py +0 -0
  29. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/policy.py +0 -0
  30. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/published_record_source.py +0 -0
  31. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/replay_cache.py +0 -0
  32. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/revert.py +0 -0
  33. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/rules.py +0 -0
  34. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/state.py +0 -0
  35. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/static/approve.html +0 -0
  36. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/static/approve.js +0 -0
  37. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle/verifier.py +0 -0
  38. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle_receipts.egg-info/SOURCES.txt +0 -0
  39. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle_receipts.egg-info/dependency_links.txt +0 -0
  40. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle_receipts.egg-info/entry_points.txt +0 -0
  41. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle_receipts.egg-info/requires.txt +0 -0
  42. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/gargoyle_receipts.egg-info/top_level.txt +0 -0
  43. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/setup.cfg +0 -0
  44. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_annotations.py +0 -0
  45. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_approver_cli.py +0 -0
  46. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_approvers.py +0 -0
  47. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_canonical.py +0 -0
  48. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_cli.py +0 -0
  49. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_console_js.py +0 -0
  50. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_consumer.py +0 -0
  51. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_entra_identity.py +0 -0
  52. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_entra_login.py +0 -0
  53. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_evidence.py +0 -0
  54. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_execution.py +0 -0
  55. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_historical.py +0 -0
  56. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_identity.py +0 -0
  57. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_issuer_service.py +0 -0
  58. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_jws.py +0 -0
  59. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_mcp_proxy.py +0 -0
  60. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_mcp_self_issue.py +0 -0
  61. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_mcp_server.py +0 -0
  62. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_notify.py +0 -0
  63. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_opa.py +0 -0
  64. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_policy.py +0 -0
  65. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_published_record.py +0 -0
  66. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_revert.py +0 -0
  67. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_rules.py +0 -0
  68. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_state.py +0 -0
  69. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_stdio_encoding.py +0 -0
  70. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_threshold.py +0 -0
  71. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.1.dev0}/tests/test_typescript_conformance.py +0 -0
  72. {gargoyle_receipts-0.8.0.dev0 → gargoyle_receipts-0.8.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.8.0.dev0
3
+ Version: 0.8.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.8.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
62
+ Status: pre-release (`0.8.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.8.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
24
+ Status: pre-release (`0.8.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
@@ -57,11 +57,16 @@ class Root:
57
57
  d = self.inside(args["path"])
58
58
  return "\n".join(("[DIR] " if e.is_dir() else "[FILE] ") + e.name for e in sorted(d.iterdir())) or "(empty)"
59
59
  if name == "read_file":
60
- return self.inside(args["path"]).read_text(encoding="utf-8")
60
+ # Bytes as they are: no newline translation, so what the assistant
61
+ # reads is what the state probe hashes.
62
+ return self.inside(args["path"]).read_bytes().decode("utf-8")
61
63
  if name == "write_file":
64
+ # Bytes as given: on Windows, text mode would turn every "\n" into
65
+ # "\r\n", and a restored snapshot would no longer match its hash.
62
66
  p = self.inside(args["path"]); p.parent.mkdir(parents=True, exist_ok=True)
63
- p.write_text(args["content"], encoding="utf-8")
64
- return "wrote %d bytes to %s" % (len(args["content"].encode("utf-8")), p)
67
+ data = args["content"].encode("utf-8")
68
+ p.write_bytes(data)
69
+ return "wrote %d bytes to %s" % (len(data), p)
65
70
  if name == "create_directory":
66
71
  p = self.inside(args["path"]); p.mkdir(parents=True, exist_ok=True)
67
72
  return "created %s" % p
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gargoyle-receipts
3
- Version: 0.8.0.dev0
3
+ Version: 0.8.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.8.0.dev0`, on PyPI as `gargoyle-receipts`). The wire format is `gargoyle/3` and may
62
+ Status: pre-release (`0.8.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.8.0.dev0"
7
+ version = "0.8.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"
@@ -52,3 +52,14 @@ def test_behind_the_gate_over_stdio(tmp_path):
52
52
  assert bare["result"]["isError"] is True # no receipt, no read
53
53
  finally:
54
54
  up.close()
55
+
56
+
57
+ def test_write_and_read_are_byte_exact_whatever_the_platform_newline(tmp_path):
58
+ """A restored snapshot must hash to what it hashed before: no newline
59
+ translation on write (Windows would double every line ending) or read."""
60
+ from gargoyle.fs_server import Root
61
+ root = Root(str(tmp_path))
62
+ content = "a\r\nb\nc"
63
+ root.call("write_file", {"path": str(tmp_path / "x.md"), "content": content})
64
+ assert (tmp_path / "x.md").read_bytes() == content.encode("utf-8")
65
+ assert root.call("read_file", {"path": str(tmp_path / "x.md")}) == content