reeve 0.0.1 → 0.2.0

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 (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +191 -0
  3. data/README.md +280 -17
  4. data/lib/generators/reeve/install/install_generator.rb +46 -0
  5. data/lib/generators/reeve/install/templates/create_audit_entries.rb.tt +77 -0
  6. data/lib/generators/reeve/install/templates/initializer.rb.tt +65 -0
  7. data/lib/reeve/audit/entry.rb +54 -0
  8. data/lib/reeve/audit/query.rb +84 -0
  9. data/lib/reeve/audit/recorder.rb +181 -0
  10. data/lib/reeve/audit/redactor.rb +67 -0
  11. data/lib/reeve/audit.rb +97 -0
  12. data/lib/reeve/authorization/adapter.rb +71 -0
  13. data/lib/reeve/authorization/adapters/plain.rb +65 -0
  14. data/lib/reeve/authorization/adapters/pundit.rb +97 -0
  15. data/lib/reeve/authorization/authorizer.rb +23 -0
  16. data/lib/reeve/authorization/current.rb +66 -0
  17. data/lib/reeve/authorization/declaration.rb +73 -0
  18. data/lib/reeve/authorization/guard.rb +97 -0
  19. data/lib/reeve/authorization/registry.rb +118 -0
  20. data/lib/reeve/authorization/scoper.rb +399 -0
  21. data/lib/reeve/authorization.rb +76 -0
  22. data/lib/reeve/configuration.rb +158 -0
  23. data/lib/reeve/context.rb +111 -0
  24. data/lib/reeve/decision.rb +111 -0
  25. data/lib/reeve/errors.rb +89 -0
  26. data/lib/reeve/fast_mcp.rb +24 -0
  27. data/lib/reeve/integrations/fast_mcp/context_builder.rb +48 -0
  28. data/lib/reeve/integrations/fast_mcp/tool_extension.rb +55 -0
  29. data/lib/reeve/invocation.rb +260 -0
  30. data/lib/reeve/minitest.rb +19 -0
  31. data/lib/reeve/rspec.rb +18 -0
  32. data/lib/reeve/scope_result.rb +104 -0
  33. data/lib/reeve/testing/assertions.rb +76 -0
  34. data/lib/reeve/testing/checks/audit_coverage.rb +46 -0
  35. data/lib/reeve/testing/checks/base.rb +155 -0
  36. data/lib/reeve/testing/checks/contract_version.rb +97 -0
  37. data/lib/reeve/testing/checks/cross_principal_leak.rb +132 -0
  38. data/lib/reeve/testing/checks/guard_declared.rb +33 -0
  39. data/lib/reeve/testing/checks/principal_required.rb +60 -0
  40. data/lib/reeve/testing/checks/redaction_holds.rb +142 -0
  41. data/lib/reeve/testing/checks/rule_present.rb +55 -0
  42. data/lib/reeve/testing/checks.rb +95 -0
  43. data/lib/reeve/testing/compliance_assertions.rb +34 -0
  44. data/lib/reeve/testing/compliance_suite.rb +23 -0
  45. data/lib/reeve/testing/ledger.rb +82 -0
  46. data/lib/reeve/testing/matchers/audit_every_call.rb +39 -0
  47. data/lib/reeve/testing/matchers/base.rb +84 -0
  48. data/lib/reeve/testing/matchers/deny_access_for.rb +38 -0
  49. data/lib/reeve/testing/matchers/pass_reeve_check.rb +32 -0
  50. data/lib/reeve/testing/matchers.rb +33 -0
  51. data/lib/reeve/testing/report.rb +58 -0
  52. data/lib/reeve/testing/result.rb +49 -0
  53. data/lib/reeve/testing.rb +60 -0
  54. data/lib/reeve/version.rb +1 -1
  55. data/lib/reeve.rb +10 -3
  56. metadata +53 -2
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "matchers/base"
4
+ require_relative "matchers/deny_access_for"
5
+ require_relative "matchers/audit_every_call"
6
+ require_relative "matchers/pass_reeve_check"
7
+
8
+ module Reeve
9
+ module Testing
10
+ # The RSpec front-end.
11
+ #
12
+ # require "reeve/rspec"
13
+ # RSpec.configure { |c| c.include Reeve::Testing::Matchers }
14
+ #
15
+ # RSpec.describe InvoiceSearchTool do
16
+ # it { is_expected.to deny_access_for(stranger).with(query: "AC") }
17
+ # it { is_expected.to audit_every_call }
18
+ # end
19
+ module Matchers
20
+ def deny_access_for(principal)
21
+ DenyAccessFor.new(principal)
22
+ end
23
+
24
+ def audit_every_call
25
+ AuditEveryCall.new
26
+ end
27
+
28
+ def pass_reeve_check
29
+ PassReeveCheck.new
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reeve
4
+ module Testing
5
+ # The aggregate of one compliance run (FR-018).
6
+ #
7
+ # +to_s+ is written to be the whole output of a failing CI step: a one-line verdict
8
+ # followed by every failure in full. A report that has to be cross-referenced with
9
+ # something else is a report nobody reads at 3am.
10
+ class Report
11
+ attr_reader :results
12
+
13
+ def initialize(results)
14
+ @results = results.freeze
15
+ freeze
16
+ end
17
+
18
+ def passed?
19
+ failures.empty?
20
+ end
21
+
22
+ def failed?
23
+ !passed?
24
+ end
25
+
26
+ def failures
27
+ results.reject(&:passed?)
28
+ end
29
+
30
+ def passes
31
+ results.select(&:passed?)
32
+ end
33
+
34
+ def size
35
+ results.size
36
+ end
37
+
38
+ def to_s
39
+ [summary, *failures.map { |result| detail(result) }].join("\n")
40
+ end
41
+
42
+ def inspect
43
+ "#<Reeve::Testing::Report #{summary}>"
44
+ end
45
+
46
+ private
47
+
48
+ def summary
49
+ "reeve compliance: #{size} #{size == 1 ? 'check' : 'checks'}, " \
50
+ "#{passes.size} passed, #{failures.size} failed"
51
+ end
52
+
53
+ def detail(result)
54
+ "\nFAIL #{result.check}\n #{result.message}"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reeve
4
+ module Testing
5
+ # What a check hands back: whether the guarantee held, the sentence explaining it, and
6
+ # the structured facts behind the sentence.
7
+ #
8
+ # The message is built here and nowhere else. A front-end — an RSpec matcher, a
9
+ # Minitest assertion, a rake task — reads +message+ and prints it; none of them
10
+ # composes their own (FR-019). That is what makes the same violation read identically
11
+ # from all three.
12
+ class Result
13
+ attr_reader :check, :message, :details
14
+
15
+ def self.passed(check:, message:, details: {})
16
+ new(check: check, passed: true, message: message, details: details)
17
+ end
18
+
19
+ def self.failed(check:, message:, details: {})
20
+ new(check: check, passed: false, message: message, details: details)
21
+ end
22
+
23
+ def initialize(check:, passed:, message:, details: {})
24
+ @check = check.to_s
25
+ @passed = passed ? true : false
26
+ @message = message.to_s
27
+ @details = details.freeze
28
+ freeze
29
+ end
30
+
31
+ def passed?
32
+ @passed
33
+ end
34
+
35
+ def failed?
36
+ !@passed
37
+ end
38
+
39
+ def to_s
40
+ message
41
+ end
42
+
43
+ def inspect
44
+ "#<Reeve::Testing::Result #{check} #{passed? ? 'passed' : 'failed'} " \
45
+ "#{message.inspect}>"
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../reeve"
4
+ require_relative "testing/result"
5
+ require_relative "testing/report"
6
+ require_relative "testing/ledger"
7
+ require_relative "testing/checks"
8
+
9
+ module Reeve
10
+ # The testing kit: framework-neutral checks, and thin front-ends over them.
11
+ #
12
+ # require "reeve/testing" # the checks, and nothing else
13
+ # require "reeve/rspec" # + matchers and the shared example group
14
+ # require "reeve/minitest" # + assertions and the compliance test case
15
+ #
16
+ # This file loads no test framework and no ActiveRecord, so the checks are runnable from
17
+ # a rake task, a CI script or a boot-time assertion in staging (FR-020, FR-026):
18
+ #
19
+ # require "reeve/testing"
20
+ # report = Reeve::Checks.run_all(principals: [alice, bob])
21
+ # abort report.to_s unless report.passed?
22
+ module Testing
23
+ class << self
24
+ # The two fixture principals the compliance suite runs every tool against. Set once,
25
+ # in the host's test helper, and both front-ends' compliance suites pick it up:
26
+ #
27
+ # Reeve::Testing.compliance_principals = -> { [users(:alice), users(:bob)] }
28
+ #
29
+ # A callable rather than a value, because in a Rails test suite the fixtures do not
30
+ # exist yet at the moment the helper is loaded.
31
+ attr_writer :compliance_principals
32
+
33
+ def compliance_principals
34
+ source = @compliance_principals || Reeve.config.compliance_principals
35
+ raise ConfigurationError, missing_principals_message if source.nil?
36
+
37
+ principals = Array(source.respond_to?(:call) ? source.call : source)
38
+ raise ConfigurationError, missing_principals_message if principals.size < 2
39
+
40
+ principals
41
+ end
42
+
43
+ def compliance_principals?
44
+ !(@compliance_principals || Reeve.config.compliance_principals).nil?
45
+ end
46
+
47
+ def reset!
48
+ @compliance_principals = nil
49
+ end
50
+
51
+ private
52
+
53
+ def missing_principals_message
54
+ "the reeve compliance suite needs two fixture principals with disjoint records. " \
55
+ "Set them in your test helper:\n\n " \
56
+ "Reeve::Testing.compliance_principals = -> { [users(:alice), users(:bob)] }"
57
+ end
58
+ end
59
+ end
60
+ end
data/lib/reeve/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reeve
4
- VERSION = "0.0.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/reeve.rb CHANGED
@@ -1,12 +1,19 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "reeve/version"
4
+ require_relative "reeve/errors"
5
+ require_relative "reeve/decision"
6
+ require_relative "reeve/configuration"
7
+ require_relative "reeve/context"
8
+ require_relative "reeve/scope_result"
9
+ require_relative "reeve/invocation"
10
+ require_relative "reeve/authorization"
4
11
 
5
12
  # Reeve — per-record authorization and an append-only audit ledger for the MCP tools
6
13
  # a Rails application exposes to AI agents.
7
14
  #
8
- # 0.0.1 is a placeholder release reserving the gem name. It has no functionality yet.
9
- # See https://github.com/vicmaster/reeve for progress.
15
+ # A tool declares the policy that governs it with `guard_with`; every invocation is
16
+ # authorized, scoped to what the principal may see, and recorded. See
17
+ # https://github.com/vicmaster/reeve.
10
18
  module Reeve
11
- class Error < StandardError; end
12
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reeve
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Velazquez
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-08-11 00:00:00.000000000 Z
11
+ date: 2026-08-12 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Reeve makes it safe for a Rails application to expose MCP (Model Context Protocol)
@@ -27,7 +27,57 @@ files:
27
27
  - CHANGELOG.md
28
28
  - LICENSE.txt
29
29
  - README.md
30
+ - lib/generators/reeve/install/install_generator.rb
31
+ - lib/generators/reeve/install/templates/create_audit_entries.rb.tt
32
+ - lib/generators/reeve/install/templates/initializer.rb.tt
30
33
  - lib/reeve.rb
34
+ - lib/reeve/audit.rb
35
+ - lib/reeve/audit/entry.rb
36
+ - lib/reeve/audit/query.rb
37
+ - lib/reeve/audit/recorder.rb
38
+ - lib/reeve/audit/redactor.rb
39
+ - lib/reeve/authorization.rb
40
+ - lib/reeve/authorization/adapter.rb
41
+ - lib/reeve/authorization/adapters/plain.rb
42
+ - lib/reeve/authorization/adapters/pundit.rb
43
+ - lib/reeve/authorization/authorizer.rb
44
+ - lib/reeve/authorization/current.rb
45
+ - lib/reeve/authorization/declaration.rb
46
+ - lib/reeve/authorization/guard.rb
47
+ - lib/reeve/authorization/registry.rb
48
+ - lib/reeve/authorization/scoper.rb
49
+ - lib/reeve/configuration.rb
50
+ - lib/reeve/context.rb
51
+ - lib/reeve/decision.rb
52
+ - lib/reeve/errors.rb
53
+ - lib/reeve/fast_mcp.rb
54
+ - lib/reeve/integrations/fast_mcp/context_builder.rb
55
+ - lib/reeve/integrations/fast_mcp/tool_extension.rb
56
+ - lib/reeve/invocation.rb
57
+ - lib/reeve/minitest.rb
58
+ - lib/reeve/rspec.rb
59
+ - lib/reeve/scope_result.rb
60
+ - lib/reeve/testing.rb
61
+ - lib/reeve/testing/assertions.rb
62
+ - lib/reeve/testing/checks.rb
63
+ - lib/reeve/testing/checks/audit_coverage.rb
64
+ - lib/reeve/testing/checks/base.rb
65
+ - lib/reeve/testing/checks/contract_version.rb
66
+ - lib/reeve/testing/checks/cross_principal_leak.rb
67
+ - lib/reeve/testing/checks/guard_declared.rb
68
+ - lib/reeve/testing/checks/principal_required.rb
69
+ - lib/reeve/testing/checks/redaction_holds.rb
70
+ - lib/reeve/testing/checks/rule_present.rb
71
+ - lib/reeve/testing/compliance_assertions.rb
72
+ - lib/reeve/testing/compliance_suite.rb
73
+ - lib/reeve/testing/ledger.rb
74
+ - lib/reeve/testing/matchers.rb
75
+ - lib/reeve/testing/matchers/audit_every_call.rb
76
+ - lib/reeve/testing/matchers/base.rb
77
+ - lib/reeve/testing/matchers/deny_access_for.rb
78
+ - lib/reeve/testing/matchers/pass_reeve_check.rb
79
+ - lib/reeve/testing/report.rb
80
+ - lib/reeve/testing/result.rb
31
81
  - lib/reeve/version.rb
32
82
  homepage: https://github.com/vicmaster/reeve
33
83
  licenses:
@@ -37,6 +87,7 @@ metadata:
37
87
  source_code_uri: https://github.com/vicmaster/reeve
38
88
  changelog_uri: https://github.com/vicmaster/reeve/blob/main/CHANGELOG.md
39
89
  bug_tracker_uri: https://github.com/vicmaster/reeve/issues
90
+ rubygems_mfa_required: 'true'
40
91
  post_install_message:
41
92
  rdoc_options: []
42
93
  require_paths: