lex-extinction 0.2.0 → 0.2.2
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.
- checksums.yaml +4 -4
- data/lib/legion/extensions/extinction/actors/protocol_monitor.rb +61 -24
- data/lib/legion/extensions/extinction/client.rb +6 -8
- data/lib/legion/extensions/extinction/helpers/archiver.rb +58 -0
- data/lib/legion/extensions/extinction/helpers/levels.rb +43 -18
- data/lib/legion/extensions/extinction/helpers/protocol_state.rb +67 -73
- data/lib/legion/extensions/extinction/runners/extinction.rb +125 -79
- data/lib/legion/extensions/extinction/settings.rb +26 -0
- data/lib/legion/extensions/extinction/version.rb +1 -1
- data/lib/legion/extensions/extinction.rb +12 -12
- metadata +148 -16
- data/Gemfile +0 -10
- data/lex-extinction.gemspec +0 -28
- data/lib/legion/extensions/extinction/local_migrations/20260316000040_create_extinction_state.rb +0 -13
- data/spec/legion/extensions/extinction/actors/protocol_monitor_spec.rb +0 -45
- data/spec/legion/extensions/extinction/client_spec.rb +0 -13
- data/spec/legion/extensions/extinction/helpers/levels_spec.rb +0 -180
- data/spec/legion/extensions/extinction/helpers/protocol_state_spec.rb +0 -291
- data/spec/legion/extensions/extinction/runners/extinction_spec.rb +0 -114
- data/spec/local_persistence_spec.rb +0 -188
- data/spec/spec_helper.rb +0 -20
|
@@ -1,188 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'sequel'
|
|
4
|
-
require 'sequel/extensions/migration'
|
|
5
|
-
|
|
6
|
-
require 'legion/extensions/extinction/helpers/levels'
|
|
7
|
-
require 'legion/extensions/extinction/helpers/protocol_state'
|
|
8
|
-
|
|
9
|
-
MIGRATIONS_PATH = File.expand_path(
|
|
10
|
-
'../lib/legion/extensions/extinction/local_migrations',
|
|
11
|
-
__dir__
|
|
12
|
-
).freeze
|
|
13
|
-
|
|
14
|
-
# Minimal stub for Legion::Data::Local used only within this spec file.
|
|
15
|
-
module Legion
|
|
16
|
-
module Data
|
|
17
|
-
module Local
|
|
18
|
-
class << self
|
|
19
|
-
attr_accessor :_connection, :_connected
|
|
20
|
-
|
|
21
|
-
def connection
|
|
22
|
-
_connection
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def connected?
|
|
26
|
-
_connected == true
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def reset_test!
|
|
30
|
-
self._connection = nil
|
|
31
|
-
self._connected = false
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
RSpec.describe Legion::Extensions::Extinction::Helpers::ProtocolState do
|
|
39
|
-
let(:db) do
|
|
40
|
-
conn = Sequel.sqlite
|
|
41
|
-
Sequel::TimestampMigrator.new(conn, MIGRATIONS_PATH).run
|
|
42
|
-
conn
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
before do
|
|
46
|
-
Legion::Data::Local._connection = db
|
|
47
|
-
Legion::Data::Local._connected = true
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
after do
|
|
51
|
-
Legion::Data::Local.reset_test!
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
describe 'save and load round-trip' do
|
|
55
|
-
it 'persists current_level via save_to_local and restores it on a new instance' do
|
|
56
|
-
state = described_class.new
|
|
57
|
-
state.escalate(1, authority: :governance_council, reason: 'test threat')
|
|
58
|
-
state.save_to_local
|
|
59
|
-
|
|
60
|
-
restored = described_class.new
|
|
61
|
-
expect(restored.current_level).to eq(1)
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
it 'persists active flag' do
|
|
65
|
-
state = described_class.new
|
|
66
|
-
state.escalate(1, authority: :governance_council, reason: 'threat')
|
|
67
|
-
state.save_to_local
|
|
68
|
-
|
|
69
|
-
restored = described_class.new
|
|
70
|
-
expect(restored.active).to be true
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
it 'persists history entries' do
|
|
74
|
-
state = described_class.new
|
|
75
|
-
state.escalate(1, authority: :governance_council, reason: 'threat')
|
|
76
|
-
state.save_to_local
|
|
77
|
-
|
|
78
|
-
restored = described_class.new
|
|
79
|
-
expect(restored.history.size).to eq(1)
|
|
80
|
-
expect(restored.history.first[:action]).to eq(:escalate)
|
|
81
|
-
expect(restored.history.first[:level]).to eq(1)
|
|
82
|
-
expect(restored.history.first[:reason]).to eq('threat')
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it 'restores history :at as a Time object' do
|
|
86
|
-
state = described_class.new
|
|
87
|
-
state.escalate(1, authority: :governance_council, reason: 'threat')
|
|
88
|
-
state.save_to_local
|
|
89
|
-
|
|
90
|
-
restored = described_class.new
|
|
91
|
-
expect(restored.history.first[:at]).to be_a(Time)
|
|
92
|
-
end
|
|
93
|
-
|
|
94
|
-
it 'saves and loads an inactive protocol at level 0' do
|
|
95
|
-
state = described_class.new
|
|
96
|
-
# state is at level 0, no escalation
|
|
97
|
-
state.save_to_local
|
|
98
|
-
|
|
99
|
-
restored = described_class.new
|
|
100
|
-
expect(restored.current_level).to eq(0)
|
|
101
|
-
expect(restored.active).to be false
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
it 'updates the existing row on a second save rather than inserting a duplicate' do
|
|
105
|
-
state = described_class.new
|
|
106
|
-
state.escalate(1, authority: :governance_council, reason: 'first')
|
|
107
|
-
state.save_to_local
|
|
108
|
-
|
|
109
|
-
state.escalate(2, authority: :governance_council, reason: 'second')
|
|
110
|
-
state.save_to_local
|
|
111
|
-
|
|
112
|
-
expect(db[:extinction_state].count).to eq(1)
|
|
113
|
-
|
|
114
|
-
restored = described_class.new
|
|
115
|
-
expect(restored.current_level).to eq(2)
|
|
116
|
-
end
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
describe 'level-4 irreversibility across restarts' do
|
|
120
|
-
it 'starts at level 4 when DB contains level 4' do
|
|
121
|
-
# Directly insert a level-4 row to simulate a previous escalation
|
|
122
|
-
db[:extinction_state].insert(
|
|
123
|
-
id: 1,
|
|
124
|
-
current_level: 4,
|
|
125
|
-
active: true,
|
|
126
|
-
history: '[]',
|
|
127
|
-
updated_at: Time.now.utc
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
state = described_class.new
|
|
131
|
-
expect(state.current_level).to eq(4)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
it 'cannot be de-escalated after reloading level 4 from DB' do
|
|
135
|
-
db[:extinction_state].insert(
|
|
136
|
-
id: 1,
|
|
137
|
-
current_level: 4,
|
|
138
|
-
active: true,
|
|
139
|
-
history: '[]',
|
|
140
|
-
updated_at: Time.now.utc
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
state = described_class.new
|
|
144
|
-
result = state.deescalate(0, authority: :physical_keyholders, reason: 'trying to escape')
|
|
145
|
-
expect(result).to eq(:irreversible)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
it 'uses max(db_level, in-memory level) so a fresh instance never drops below DB level' do
|
|
149
|
-
db[:extinction_state].insert(
|
|
150
|
-
id: 1,
|
|
151
|
-
current_level: 3,
|
|
152
|
-
active: true,
|
|
153
|
-
history: '[]',
|
|
154
|
-
updated_at: Time.now.utc
|
|
155
|
-
)
|
|
156
|
-
|
|
157
|
-
state = described_class.new
|
|
158
|
-
# In-memory starts at 0, DB has 3, so max(3, 0) = 3
|
|
159
|
-
expect(state.current_level).to eq(3)
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
describe 'graceful no-op when Local is not connected' do
|
|
164
|
-
before do
|
|
165
|
-
Legion::Data::Local._connected = false
|
|
166
|
-
Legion::Data::Local._connection = nil
|
|
167
|
-
end
|
|
168
|
-
|
|
169
|
-
it 'initializes normally when Local is disconnected' do
|
|
170
|
-
state = described_class.new
|
|
171
|
-
expect(state.current_level).to eq(0)
|
|
172
|
-
expect(state.active).to be false
|
|
173
|
-
expect(state.history).to eq([])
|
|
174
|
-
end
|
|
175
|
-
|
|
176
|
-
it 'save_to_local returns nil without raising when disconnected' do
|
|
177
|
-
state = described_class.new
|
|
178
|
-
expect { state.save_to_local }.not_to raise_error
|
|
179
|
-
end
|
|
180
|
-
|
|
181
|
-
it 'does not mutate state during save_to_local when disconnected' do
|
|
182
|
-
state = described_class.new
|
|
183
|
-
state.escalate(1, authority: :governance_council, reason: 'test')
|
|
184
|
-
state.save_to_local
|
|
185
|
-
expect(state.current_level).to eq(1)
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require 'bundler/setup'
|
|
4
|
-
|
|
5
|
-
module Legion
|
|
6
|
-
module Logging
|
|
7
|
-
def self.debug(_msg); end
|
|
8
|
-
def self.info(_msg); end
|
|
9
|
-
def self.warn(_msg); end
|
|
10
|
-
def self.error(_msg); end
|
|
11
|
-
end
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
require 'legion/extensions/extinction'
|
|
15
|
-
|
|
16
|
-
RSpec.configure do |config|
|
|
17
|
-
config.example_status_persistence_file_path = '.rspec_status'
|
|
18
|
-
config.disable_monkey_patching!
|
|
19
|
-
config.expect_with(:rspec) { |c| c.syntax = :expect }
|
|
20
|
-
end
|