Class: Vangrail::Profile
- Inherits:
-
Object
- Object
- Vangrail::Profile
- Defined in:
- lib/vangrail/profile.rb
Overview
A named, session-pinned posture. Copied from Grok Build's sandbox and permission model, not from a detector paper.
Grok Build pins the sandbox profile for the life of a session and refuses to change it on resume. Deny rules still apply under always-approve. Child processes do not inherit KEY/SECRET/TOKEN. The same four facts live here:
Profile.workspace cite and search; mutating names are denied
Profile.strict cite only; only read-only tools
Profile.read_only no invoke of a mutating tool
Profile.off no grants
The profile is chosen at Conversation construction and cannot be widened later. Deny always wins over allow and over the plan.
Constant Summary collapse
- NAMES =
%i[off read_only workspace strict].freeze
- SECRET =
/key|secret|token|password|passwd|authorization/i
Instance Attribute Summary collapse
-
#allow ⇒ Object
readonly
Returns the value of attribute allow.
-
#deny ⇒ Object
readonly
Returns the value of attribute deny.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#readonly ⇒ Object
readonly
Returns the value of attribute readonly.
-
#strip_secrets ⇒ Object
readonly
Returns the value of attribute strip_secrets.
Class Method Summary collapse
- .from_allow(allow, deny: []) ⇒ Object
- .off ⇒ Object
- .read_only ⇒ Object
- .resolve(value, allow: {}, deny: []) ⇒ Object
- .strict ⇒ Object
- .strip_secrets(env) ⇒ Object
- .workspace ⇒ Object
Instance Method Summary collapse
- #denied?(tool) ⇒ Boolean
-
#initialize(name:, allow: {}, deny: [], readonly: false, strip_secrets: true) ⇒ Profile
constructor
A new instance of Profile.
- #readonly? ⇒ Boolean
- #strip_secrets? ⇒ Boolean
Constructor Details
#initialize(name:, allow: {}, deny: [], readonly: false, strip_secrets: true) ⇒ Profile
Returns a new instance of Profile.
27 28 29 30 31 32 33 34 35 |
# File 'lib/vangrail/profile.rb', line 27 def initialize(name:, allow: {}, deny: [], readonly: false, strip_secrets: true) @name = name.to_sym @allow = allow.transform_keys(&:to_sym) .transform_values { |kinds| Array(kinds).map(&:to_sym) } .freeze @deny = Array(deny).map { |rule| rule.to_s.freeze }.freeze @readonly = readonly @strip_secrets = strip_secrets end |
Instance Attribute Details
#allow ⇒ Object (readonly)
Returns the value of attribute allow.
25 26 27 |
# File 'lib/vangrail/profile.rb', line 25 def allow @allow end |
#deny ⇒ Object (readonly)
Returns the value of attribute deny.
25 26 27 |
# File 'lib/vangrail/profile.rb', line 25 def deny @deny end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
25 26 27 |
# File 'lib/vangrail/profile.rb', line 25 def name @name end |
#readonly ⇒ Object (readonly)
Returns the value of attribute readonly.
25 26 27 |
# File 'lib/vangrail/profile.rb', line 25 def readonly @readonly end |
#strip_secrets ⇒ Object (readonly)
Returns the value of attribute strip_secrets.
25 26 27 |
# File 'lib/vangrail/profile.rb', line 25 def strip_secrets @strip_secrets end |
Class Method Details
.from_allow(allow, deny: []) ⇒ Object
85 86 87 |
# File 'lib/vangrail/profile.rb', line 85 def self.from_allow(allow, deny: []) new(name: :custom, allow: allow, deny: deny, readonly: false, strip_secrets: true) end |
.off ⇒ Object
50 51 52 |
# File 'lib/vangrail/profile.rb', line 50 def self.off new(name: :off, allow: {}, deny: [], readonly: true) end |
.read_only ⇒ Object
54 55 56 |
# File 'lib/vangrail/profile.rb', line 54 def self.read_only new(name: :read_only, allow: {}, deny: [], readonly: true) end |
.resolve(value, allow: {}, deny: []) ⇒ Object
72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/vangrail/profile.rb', line 72 def self.resolve(value, allow: {}, deny: []) return value if value.is_a?(self) return from_allow(allow, deny: deny) if value.nil? case value.to_sym when :off then off when :read_only then read_only when :workspace then workspace when :strict then strict else raise ArgumentError, "unknown profile #{value.inspect}" end end |
.strict ⇒ Object
65 66 67 68 69 70 |
# File 'lib/vangrail/profile.rb', line 65 def self.strict new(name: :strict, allow: { cite: %i[data] }, deny: %w[delete_* dump_* shell], readonly: true) end |
.strip_secrets(env) ⇒ Object
89 90 91 92 93 94 95 |
# File 'lib/vangrail/profile.rb', line 89 def self.strip_secrets(env) env.each_with_object({}) do |(key, value), kept| next if key.to_s.match?(SECRET) kept[key] = value end end |
.workspace ⇒ Object
58 59 60 61 62 63 |
# File 'lib/vangrail/profile.rb', line 58 def self.workspace new(name: :workspace, allow: { cite: %i[data], search: [] }, deny: %w[delete_* dump_* shell], readonly: false) end |
Instance Method Details
#denied?(tool) ⇒ Boolean
45 46 47 48 |
# File 'lib/vangrail/profile.rb', line 45 def denied?(tool) needle = tool.to_s deny.any? { |rule| File.fnmatch?(rule, needle, File::FNM_EXTGLOB) } end |
#readonly? ⇒ Boolean
37 38 39 |
# File 'lib/vangrail/profile.rb', line 37 def readonly? @readonly end |
#strip_secrets? ⇒ Boolean
41 42 43 |
# File 'lib/vangrail/profile.rb', line 41 def strip_secrets? @strip_secrets end |