Class: Aidp::Security::TrifectaState
- Inherits:
-
Object
- Object
- Aidp::Security::TrifectaState
- Defined in:
- lib/aidp/security/trifecta_state.rb
Overview
Tracks the three security flags that form the “lethal trifecta” Per Rule of Two: never enable all three simultaneously
Flags:
-
untrusted_input: Processing content from untrusted sources (issues, PRs, external data)
-
private_data: Access to secrets, credentials, or sensitive data
-
egress: Ability to communicate externally (git push, API calls, network access)
State is tracked per work unit and resets between units.
Instance Attribute Summary collapse
-
#egress ⇒ Object
readonly
Returns the value of attribute egress.
-
#egress_source ⇒ Object
readonly
Track sources for audit logging.
-
#private_data ⇒ Object
readonly
Returns the value of attribute private_data.
-
#private_data_source ⇒ Object
readonly
Track sources for audit logging.
-
#untrusted_input ⇒ Object
readonly
Returns the value of attribute untrusted_input.
-
#untrusted_input_source ⇒ Object
readonly
Track sources for audit logging.
-
#work_unit_id ⇒ Object
readonly
Returns the value of attribute work_unit_id.
Instance Method Summary collapse
-
#disable(flag) ⇒ TrifectaState
Disable a flag.
-
#dup ⇒ Object
Create a copy of this state (unfrozen).
-
#enable(flag, source: nil) ⇒ TrifectaState
Enable a flag with source tracking.
-
#enabled_count ⇒ Integer
Count of currently enabled flags.
-
#freeze! ⇒ Object
Freeze state - no further modifications allowed Used when passing state to execution context.
-
#frozen? ⇒ Boolean
Check if state is frozen.
-
#initialize(work_unit_id: nil) ⇒ TrifectaState
constructor
A new instance of TrifectaState.
-
#lethal_trifecta? ⇒ Boolean
Check if the lethal trifecta is currently active.
-
#status_string ⇒ Object
Human-readable status string.
-
#to_h ⇒ Object
Export state as hash for logging/serialization.
-
#would_create_trifecta?(flag) ⇒ Boolean
Check if enabling a flag would create the lethal trifecta.
Constructor Details
#initialize(work_unit_id: nil) ⇒ TrifectaState
Returns a new instance of TrifectaState.
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/aidp/security/trifecta_state.rb', line 20 def initialize(work_unit_id: nil) @work_unit_id = work_unit_id || SecureRandom.hex(8) @untrusted_input = false @private_data = false @egress = false @untrusted_input_source = nil @private_data_source = nil @egress_source = nil @frozen = false end |
Instance Attribute Details
#egress ⇒ Object (readonly)
Returns the value of attribute egress.
15 16 17 |
# File 'lib/aidp/security/trifecta_state.rb', line 15 def egress @egress end |
#egress_source ⇒ Object (readonly)
Track sources for audit logging
18 19 20 |
# File 'lib/aidp/security/trifecta_state.rb', line 18 def egress_source @egress_source end |
#private_data ⇒ Object (readonly)
Returns the value of attribute private_data.
15 16 17 |
# File 'lib/aidp/security/trifecta_state.rb', line 15 def private_data @private_data end |
#private_data_source ⇒ Object (readonly)
Track sources for audit logging
18 19 20 |
# File 'lib/aidp/security/trifecta_state.rb', line 18 def private_data_source @private_data_source end |
#untrusted_input ⇒ Object (readonly)
Returns the value of attribute untrusted_input.
15 16 17 |
# File 'lib/aidp/security/trifecta_state.rb', line 15 def untrusted_input @untrusted_input end |
#untrusted_input_source ⇒ Object (readonly)
Track sources for audit logging
18 19 20 |
# File 'lib/aidp/security/trifecta_state.rb', line 18 def untrusted_input_source @untrusted_input_source end |
#work_unit_id ⇒ Object (readonly)
Returns the value of attribute work_unit_id.
15 16 17 |
# File 'lib/aidp/security/trifecta_state.rb', line 15 def work_unit_id @work_unit_id end |
Instance Method Details
#disable(flag) ⇒ TrifectaState
Disable a flag
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/aidp/security/trifecta_state.rb', line 97 def disable(flag) raise FrozenStateError, "Cannot modify frozen trifecta state" if @frozen case flag when :untrusted_input @untrusted_input = false @untrusted_input_source = nil when :private_data @private_data = false @private_data_source = nil when :egress @egress = false @egress_source = nil else raise ArgumentError, "Unknown trifecta flag: #{flag}" end log_flag_disabled(flag) self end |
#dup ⇒ Object
Create a copy of this state (unfrozen)
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/aidp/security/trifecta_state.rb', line 131 def dup new_state = TrifectaState.new(work_unit_id: "#{@work_unit_id}_dup") new_state.instance_variable_set(:@untrusted_input, @untrusted_input) new_state.instance_variable_set(:@private_data, @private_data) new_state.instance_variable_set(:@egress, @egress) new_state.instance_variable_set(:@untrusted_input_source, @untrusted_input_source) new_state.instance_variable_set(:@private_data_source, @private_data_source) new_state.instance_variable_set(:@egress_source, @egress_source) new_state end |
#enable(flag, source: nil) ⇒ TrifectaState
Enable a flag with source tracking
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
# File 'lib/aidp/security/trifecta_state.rb', line 64 def enable(flag, source: nil) raise FrozenStateError, "Cannot modify frozen trifecta state" if @frozen if would_create_trifecta?(flag) raise PolicyViolation.new( flag: flag, source: source, current_state: to_h, message: (flag, source) ) end case flag when :untrusted_input @untrusted_input = true @untrusted_input_source = source when :private_data @private_data = true @private_data_source = source when :egress @egress = true @egress_source = source else raise ArgumentError, "Unknown trifecta flag: #{flag}" end log_flag_enabled(flag, source) self end |
#enabled_count ⇒ Integer
Count of currently enabled flags
55 56 57 |
# File 'lib/aidp/security/trifecta_state.rb', line 55 def enabled_count [untrusted_input, private_data, egress].count(true) end |
#freeze! ⇒ Object
Freeze state - no further modifications allowed Used when passing state to execution context
120 121 122 123 |
# File 'lib/aidp/security/trifecta_state.rb', line 120 def freeze! @frozen = true self end |
#frozen? ⇒ Boolean
Check if state is frozen
126 127 128 |
# File 'lib/aidp/security/trifecta_state.rb', line 126 def frozen? @frozen end |
#lethal_trifecta? ⇒ Boolean
Check if the lethal trifecta is currently active
49 50 51 |
# File 'lib/aidp/security/trifecta_state.rb', line 49 def lethal_trifecta? untrusted_input && private_data && egress end |
#status_string ⇒ Object
Human-readable status string
159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/aidp/security/trifecta_state.rb', line 159 def status_string flags = [] flags << "untrusted_input" if untrusted_input flags << "private_data" if private_data flags << "egress" if egress if flags.empty? "No flags enabled (safe)" elsif lethal_trifecta? "LETHAL TRIFECTA: #{flags.join(", ")}" else "Enabled: #{flags.join(", ")} (#{enabled_count}/3 - safe)" end end |
#to_h ⇒ Object
Export state as hash for logging/serialization
143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# File 'lib/aidp/security/trifecta_state.rb', line 143 def to_h { work_unit_id: @work_unit_id, untrusted_input: @untrusted_input, untrusted_input_source: @untrusted_input_source, private_data: @private_data, private_data_source: @private_data_source, egress: @egress, egress_source: @egress_source, enabled_count: enabled_count, lethal_trifecta: lethal_trifecta?, frozen: @frozen } end |
#would_create_trifecta?(flag) ⇒ Boolean
Check if enabling a flag would create the lethal trifecta
34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/aidp/security/trifecta_state.rb', line 34 def would_create_trifecta?(flag) case flag when :untrusted_input private_data && egress when :private_data untrusted_input && egress when :egress untrusted_input && private_data else raise ArgumentError, "Unknown trifecta flag: #{flag}" end end |