pg_sql_triggers 1.2.0 → 1.3.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +144 -0
  3. data/COVERAGE.md +26 -19
  4. data/Goal.md +276 -155
  5. data/README.md +27 -1
  6. data/app/assets/javascripts/pg_sql_triggers/trigger_actions.js +50 -0
  7. data/app/controllers/concerns/pg_sql_triggers/error_handling.rb +56 -0
  8. data/app/controllers/concerns/pg_sql_triggers/kill_switch_protection.rb +66 -0
  9. data/app/controllers/concerns/pg_sql_triggers/permission_checking.rb +117 -0
  10. data/app/controllers/pg_sql_triggers/application_controller.rb +10 -62
  11. data/app/controllers/pg_sql_triggers/audit_logs_controller.rb +102 -0
  12. data/app/controllers/pg_sql_triggers/dashboard_controller.rb +4 -9
  13. data/app/controllers/pg_sql_triggers/tables_controller.rb +30 -4
  14. data/app/controllers/pg_sql_triggers/triggers_controller.rb +3 -21
  15. data/app/helpers/pg_sql_triggers/permissions_helper.rb +43 -0
  16. data/app/models/pg_sql_triggers/audit_log.rb +106 -0
  17. data/app/models/pg_sql_triggers/trigger_registry.rb +178 -9
  18. data/app/views/layouts/pg_sql_triggers/application.html.erb +26 -6
  19. data/app/views/pg_sql_triggers/audit_logs/index.html.erb +177 -0
  20. data/app/views/pg_sql_triggers/dashboard/index.html.erb +33 -8
  21. data/app/views/pg_sql_triggers/tables/index.html.erb +76 -3
  22. data/app/views/pg_sql_triggers/tables/show.html.erb +17 -4
  23. data/app/views/pg_sql_triggers/triggers/_drop_modal.html.erb +16 -7
  24. data/app/views/pg_sql_triggers/triggers/_re_execute_modal.html.erb +16 -7
  25. data/app/views/pg_sql_triggers/triggers/show.html.erb +26 -6
  26. data/config/routes.rb +2 -0
  27. data/db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb +28 -0
  28. data/docs/README.md +15 -5
  29. data/docs/api-reference.md +191 -0
  30. data/docs/audit-trail.md +413 -0
  31. data/docs/configuration.md +6 -6
  32. data/docs/permissions.md +369 -0
  33. data/docs/troubleshooting.md +486 -0
  34. data/docs/ui-guide.md +211 -0
  35. data/docs/web-ui.md +257 -34
  36. data/lib/pg_sql_triggers/errors.rb +245 -0
  37. data/lib/pg_sql_triggers/generator/service.rb +32 -0
  38. data/lib/pg_sql_triggers/permissions/checker.rb +9 -2
  39. data/lib/pg_sql_triggers/registry.rb +141 -8
  40. data/lib/pg_sql_triggers/sql/kill_switch.rb +33 -5
  41. data/lib/pg_sql_triggers/testing/function_tester.rb +2 -0
  42. data/lib/pg_sql_triggers/version.rb +1 -1
  43. data/lib/pg_sql_triggers.rb +3 -6
  44. metadata +29 -6
  45. data/docs/screenshots/.gitkeep +0 -1
  46. data/docs/screenshots/Generate Trigger.png +0 -0
  47. data/docs/screenshots/Triggers Page.png +0 -0
  48. data/docs/screenshots/kill error.png +0 -0
  49. data/docs/screenshots/kill modal for migration down.png +0 -0
@@ -6,9 +6,24 @@ require "active_support/core_ext/string/inflections"
6
6
 
7
7
  module PgSqlTriggers
8
8
  module Generator
9
+ # Service object for generating trigger DSL files, migration files, and registering triggers.
10
+ #
11
+ # This service follows the service object pattern with class methods for stateless operations.
12
+ #
13
+ # @example Generate trigger files
14
+ # form = PgSqlTriggers::Generator::Form.new(trigger_name: "users_email_validation", ...)
15
+ # result = PgSqlTriggers::Generator::Service.create_trigger(form, actor: current_user)
16
+ #
17
+ # if result[:success]
18
+ # puts "Created: #{result[:migration_path]}"
19
+ # end
9
20
  # rubocop:disable Metrics/ClassLength
10
21
  class Service
11
22
  class << self
23
+ # Generates the DSL trigger definition code from a form.
24
+ #
25
+ # @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
26
+ # @return [String] The generated DSL code
12
27
  def generate_dsl(form)
13
28
  # Generate DSL trigger definition
14
29
  events_list = form.events.compact_blank.map { |e| ":#{e}" }.join(", ")
@@ -44,6 +59,10 @@ module PgSqlTriggers
44
59
  code
45
60
  end
46
61
 
62
+ # Generates the migration file code from a form.
63
+ #
64
+ # @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
65
+ # @return [String] The generated migration code
47
66
  def generate_migration(form)
48
67
  # Generate migration class code
49
68
  # Use Rails migration naming convention: Add{TriggerName}
@@ -95,6 +114,10 @@ module PgSqlTriggers
95
114
  RUBY
96
115
  end
97
116
 
117
+ # Generates a PL/pgSQL function stub template.
118
+ #
119
+ # @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
120
+ # @return [String, nil] The generated function stub SQL, or nil if not requested
98
121
  def generate_function_stub(form)
99
122
  return nil unless form.generate_function_stub
100
123
 
@@ -138,6 +161,10 @@ module PgSqlTriggers
138
161
  SQL
139
162
  end
140
163
 
164
+ # Returns the file paths where the migration and DSL files will be created.
165
+ #
166
+ # @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
167
+ # @return [Hash] Hash with :migration and :dsl keys containing relative file paths
141
168
  def file_paths(form)
142
169
  # NOTE: These paths are relative to the host Rails app, not the gem
143
170
  # Generate both migration file and DSL file
@@ -148,6 +175,11 @@ module PgSqlTriggers
148
175
  }
149
176
  end
150
177
 
178
+ # Creates trigger files (DSL and migration) and registers the trigger in the registry.
179
+ #
180
+ # @param form [PgSqlTriggers::Generator::Form] The form containing trigger parameters
181
+ # @param actor [Hash, nil] Optional actor information for audit logging
182
+ # @return [Hash] Result hash with :success (Boolean), :migration_path, :dsl_path, and optional :error
151
183
  def create_trigger(form, actor: nil) # rubocop:disable Lint/UnusedMethodArgument
152
184
  paths = file_paths(form)
153
185
  base_path = rails_base_path
@@ -22,8 +22,15 @@ module PgSqlTriggers
22
22
  unless can?(actor, action, environment: environment)
23
23
  action_sym = action.to_sym
24
24
  required_level = Permissions::ACTIONS[action_sym] || "unknown"
25
- raise PgSqlTriggers::PermissionError,
26
- "Permission denied: #{action_sym} requires #{required_level} level access"
25
+ message = "Permission denied: #{action_sym} requires #{required_level} level access"
26
+ recovery = "Contact your administrator to request #{required_level} level access for this operation."
27
+
28
+ raise PgSqlTriggers::PermissionError.new(
29
+ message,
30
+ error_code: "PERMISSION_DENIED",
31
+ recovery_suggestion: recovery,
32
+ context: { action: action_sym, required_role: required_level, environment: environment }
33
+ )
27
34
  end
28
35
  true
29
36
  end
@@ -1,59 +1,187 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgSqlTriggers
4
+ # Registry module provides a unified API for querying and managing triggers.
5
+ #
6
+ # @example Query triggers
7
+ # # List all triggers
8
+ # triggers = PgSqlTriggers::Registry.list
9
+ #
10
+ # # Get enabled/disabled triggers
11
+ # enabled = PgSqlTriggers::Registry.enabled
12
+ # disabled = PgSqlTriggers::Registry.disabled
13
+ #
14
+ # # Get triggers for a specific table
15
+ # user_triggers = PgSqlTriggers::Registry.for_table(:users)
16
+ #
17
+ # # Check for drift
18
+ # drift_info = PgSqlTriggers::Registry.diff
19
+ #
20
+ # @example Manage triggers
21
+ # # Enable a trigger
22
+ # PgSqlTriggers::Registry.enable("users_email_validation",
23
+ # actor: current_user,
24
+ # confirmation: "EXECUTE TRIGGER_ENABLE")
25
+ #
26
+ # # Disable a trigger
27
+ # PgSqlTriggers::Registry.disable("users_email_validation",
28
+ # actor: current_user,
29
+ # confirmation: "EXECUTE TRIGGER_DISABLE")
30
+ #
31
+ # # Drop a trigger
32
+ # PgSqlTriggers::Registry.drop("old_trigger",
33
+ # actor: current_user,
34
+ # reason: "No longer needed",
35
+ # confirmation: "EXECUTE TRIGGER_DROP")
36
+ #
37
+ # # Re-execute a trigger
38
+ # PgSqlTriggers::Registry.re_execute("drifted_trigger",
39
+ # actor: current_user,
40
+ # reason: "Fix drift",
41
+ # confirmation: "EXECUTE TRIGGER_RE_EXECUTE")
4
42
  module Registry
5
43
  autoload :Manager, "pg_sql_triggers/registry/manager"
6
44
  autoload :Validator, "pg_sql_triggers/registry/validator"
7
45
 
46
+ # Registers a trigger definition in the registry.
47
+ #
48
+ # @param definition [PgSqlTriggers::DSL::TriggerDefinition] The trigger definition to register
49
+ # @return [PgSqlTriggers::TriggerRegistry] The registered trigger record
8
50
  def self.register(definition)
9
51
  Manager.register(definition)
10
52
  end
11
53
 
54
+ # Returns all registered triggers.
55
+ #
56
+ # @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] All trigger records
12
57
  def self.list
13
58
  Manager.list
14
59
  end
15
60
 
61
+ # Returns only enabled triggers.
62
+ #
63
+ # @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Enabled trigger records
16
64
  def self.enabled
17
65
  Manager.enabled
18
66
  end
19
67
 
68
+ # Returns only disabled triggers.
69
+ #
70
+ # @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Disabled trigger records
20
71
  def self.disabled
21
72
  Manager.disabled
22
73
  end
23
74
 
75
+ # Returns triggers for a specific table.
76
+ #
77
+ # @param table_name [String, Symbol] The table name to filter by
78
+ # @return [ActiveRecord::Relation<PgSqlTriggers::TriggerRegistry>] Triggers for the specified table
24
79
  def self.for_table(table_name)
25
80
  Manager.for_table(table_name)
26
81
  end
27
82
 
28
- def self.diff
29
- Manager.diff
83
+ # Checks for drift between DSL definitions and database state.
84
+ #
85
+ # @param trigger_name [String, nil] Optional trigger name to check specific trigger, or nil for all triggers
86
+ # @return [Hash] Drift information with keys: :in_sync, :drifted, :manual_override, :disabled, :dropped, :unknown
87
+ def self.diff(trigger_name = nil)
88
+ Manager.diff(trigger_name)
30
89
  end
31
90
 
91
+ # Returns all triggers that have drifted from their expected state.
92
+ #
93
+ # @return [Array<Hash>] Array of drift result hashes for drifted triggers
94
+ def self.drifted
95
+ Manager.drifted
96
+ end
97
+
98
+ # Returns all triggers that are in sync with their expected state.
99
+ #
100
+ # @return [Array<Hash>] Array of drift result hashes for in-sync triggers
101
+ def self.in_sync
102
+ Manager.in_sync
103
+ end
104
+
105
+ # Returns all unknown (external) triggers not managed by this gem.
106
+ #
107
+ # @return [Array<Hash>] Array of drift result hashes for unknown triggers
108
+ def self.unknown_triggers
109
+ Manager.unknown_triggers
110
+ end
111
+
112
+ # Returns all triggers that have been dropped from the database.
113
+ #
114
+ # @return [Array<Hash>] Array of drift result hashes for dropped triggers
115
+ def self.dropped
116
+ Manager.dropped
117
+ end
118
+
119
+ # Validates all triggers in the registry.
120
+ #
121
+ # @raise [PgSqlTriggers::ValidationError] If validation fails
122
+ # @return [true] If validation passes
32
123
  def self.validate!
33
124
  Validator.validate!
34
125
  end
35
126
 
36
- # Console APIs for trigger operations
37
- # These methods provide a convenient interface for managing triggers from the Rails console
38
-
127
+ # Enables a trigger by name.
128
+ #
129
+ # @param trigger_name [String] The name of the trigger to enable
130
+ # @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
131
+ # @param confirmation [String, nil] Optional confirmation text for kill switch protection
132
+ # @raise [PgSqlTriggers::PermissionError] If actor lacks permission
133
+ # @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
134
+ # @raise [PgSqlTriggers::NotFoundError] If trigger not found
135
+ # @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
39
136
  def self.enable(trigger_name, actor:, confirmation: nil)
40
137
  check_permission!(actor, :enable_trigger)
41
138
  trigger = find_trigger!(trigger_name)
42
- trigger.enable!(confirmation: confirmation)
139
+ trigger.enable!(confirmation: confirmation, actor: actor)
43
140
  end
44
141
 
142
+ # Disables a trigger by name.
143
+ #
144
+ # @param trigger_name [String] The name of the trigger to disable
145
+ # @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
146
+ # @param confirmation [String, nil] Optional confirmation text for kill switch protection
147
+ # @raise [PgSqlTriggers::PermissionError] If actor lacks permission
148
+ # @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
149
+ # @raise [PgSqlTriggers::NotFoundError] If trigger not found
150
+ # @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
45
151
  def self.disable(trigger_name, actor:, confirmation: nil)
46
152
  check_permission!(actor, :disable_trigger)
47
153
  trigger = find_trigger!(trigger_name)
48
- trigger.disable!(confirmation: confirmation)
154
+ trigger.disable!(confirmation: confirmation, actor: actor)
49
155
  end
50
156
 
157
+ # Drops a trigger by name.
158
+ #
159
+ # @param trigger_name [String] The name of the trigger to drop
160
+ # @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
161
+ # @param reason [String] Required reason for dropping the trigger
162
+ # @param confirmation [String, nil] Optional confirmation text for kill switch protection
163
+ # @raise [PgSqlTriggers::PermissionError] If actor lacks permission
164
+ # @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
165
+ # @raise [PgSqlTriggers::NotFoundError] If trigger not found
166
+ # @raise [ArgumentError] If reason is missing or empty
167
+ # @return [true] If drop succeeds
51
168
  def self.drop(trigger_name, actor:, reason:, confirmation: nil)
52
169
  check_permission!(actor, :drop_trigger)
53
170
  trigger = find_trigger!(trigger_name)
54
171
  trigger.drop!(reason: reason, confirmation: confirmation, actor: actor)
55
172
  end
56
173
 
174
+ # Re-executes a trigger by name (drops and recreates it).
175
+ #
176
+ # @param trigger_name [String] The name of the trigger to re-execute
177
+ # @param actor [Hash] Information about who is performing the action (must have :type and :id keys)
178
+ # @param reason [String] Required reason for re-executing the trigger
179
+ # @param confirmation [String, nil] Optional confirmation text for kill switch protection
180
+ # @raise [PgSqlTriggers::PermissionError] If actor lacks permission
181
+ # @raise [PgSqlTriggers::KillSwitchError] If kill switch blocks the operation
182
+ # @raise [PgSqlTriggers::NotFoundError] If trigger not found
183
+ # @raise [ArgumentError] If reason is missing or empty
184
+ # @return [PgSqlTriggers::TriggerRegistry] The updated trigger record
57
185
  def self.re_execute(trigger_name, actor:, reason:, confirmation: nil)
58
186
  check_permission!(actor, :drop_trigger) # Re-execute requires same permission as drop
59
187
  trigger = find_trigger!(trigger_name)
@@ -65,7 +193,12 @@ module PgSqlTriggers
65
193
  def self.find_trigger!(trigger_name)
66
194
  PgSqlTriggers::TriggerRegistry.find_by!(trigger_name: trigger_name)
67
195
  rescue ActiveRecord::RecordNotFound
68
- raise ArgumentError, "Trigger '#{trigger_name}' not found in registry"
196
+ raise PgSqlTriggers::NotFoundError.new(
197
+ "Trigger '#{trigger_name}' not found in registry",
198
+ error_code: "TRIGGER_NOT_FOUND",
199
+ recovery_suggestion: "Verify the trigger name or create the trigger first using the generator or DSL.",
200
+ context: { trigger_name: trigger_name }
201
+ )
69
202
  end
70
203
  private_class_method :find_trigger!
71
204
 
@@ -143,14 +143,23 @@ module PgSqlTriggers
143
143
  expected = expected_confirmation(operation)
144
144
 
145
145
  if confirmation.nil? || confirmation.strip.empty?
146
- raise PgSqlTriggers::KillSwitchError,
147
- "Confirmation text required. Expected: '#{expected}'"
146
+ raise PgSqlTriggers::KillSwitchError.new(
147
+ "Confirmation text required. Expected: '#{expected}'",
148
+ error_code: "KILL_SWITCH_CONFIRMATION_REQUIRED",
149
+ recovery_suggestion: "Provide the confirmation text: #{expected}",
150
+ context: { operation: operation, expected_confirmation: expected }
151
+ )
148
152
  end
149
153
 
150
154
  return if confirmation.strip == expected
151
155
 
152
- raise PgSqlTriggers::KillSwitchError,
153
- "Invalid confirmation text. Expected: '#{expected}', got: '#{confirmation.strip}'"
156
+ raise PgSqlTriggers::KillSwitchError.new(
157
+ "Invalid confirmation text. Expected: '#{expected}', got: '#{confirmation.strip}'",
158
+ error_code: "KILL_SWITCH_CONFIRMATION_INVALID",
159
+ recovery_suggestion: "Use the exact confirmation text: #{expected}",
160
+ context: { operation: operation, expected_confirmation: expected,
161
+ provided_confirmation: confirmation.strip }
162
+ )
154
163
  end
155
164
 
156
165
  private
@@ -291,7 +300,26 @@ module PgSqlTriggers
291
300
  Make sure you understand the implications before proceeding.
292
301
  ERROR
293
302
 
294
- raise PgSqlTriggers::KillSwitchError, message
303
+ recovery = <<~RECOVERY
304
+ To override, provide the confirmation text: #{expected}
305
+
306
+ For CLI/rake tasks:
307
+ KILL_SWITCH_OVERRIDE=true CONFIRMATION_TEXT="#{expected}" rake your:task
308
+
309
+ For console operations:
310
+ PgSqlTriggers::SQL::KillSwitch.override(confirmation: "#{expected}") do
311
+ # your operation here
312
+ end
313
+
314
+ For UI operations, enter the confirmation text in the modal.
315
+ RECOVERY
316
+
317
+ raise PgSqlTriggers::KillSwitchError.new(
318
+ message,
319
+ error_code: "KILL_SWITCH_ACTIVE",
320
+ recovery_suggestion: recovery.strip,
321
+ context: { operation: operation, environment: environment, expected_confirmation: expected }
322
+ )
295
323
  end
296
324
  end
297
325
  end
@@ -110,6 +110,8 @@ module PgSqlTriggers
110
110
  results[:function_executed] = false
111
111
  results[:success] = false
112
112
  results[:errors] << "Error during function verification: #{e.message}"
113
+ # Also add the original error message to ensure it's searchable in tests
114
+ results[:errors] << e.message unless results[:errors].include?(e.message)
113
115
  results[:output] << "✓ Function created (verification failed)"
114
116
  end
115
117
  else
@@ -11,5 +11,5 @@
11
11
  # 3. Run: bundle exec rake release
12
12
  # See RELEASE.md for detailed release instructions
13
13
  module PgSqlTriggers
14
- VERSION = "1.2.0"
14
+ VERSION = "1.3.0"
15
15
  end
@@ -1,15 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "pg_sql_triggers/version"
4
+ require_relative "pg_sql_triggers/errors"
4
5
  require_relative "pg_sql_triggers/engine"
5
6
 
6
7
  module PgSqlTriggers
7
- class Error < StandardError; end
8
- class PermissionError < Error; end
9
- class DriftError < Error; end
10
- class KillSwitchError < Error; end
11
- class ValidationError < Error; end
12
- class UnsafeMigrationError < Error; end
8
+ # Error classes are defined in lib/pg_sql_triggers/errors.rb
9
+ # They include error codes, standardized messages, and recovery suggestions
13
10
 
14
11
  # Configuration
15
12
  mattr_accessor :kill_switch_enabled
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_sql_triggers
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - samaswin
@@ -9,6 +9,20 @@ bindir: exe
9
9
  cert_chain: []
10
10
  date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: csv
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - ">="
17
+ - !ruby/object:Gem::Version
18
+ version: '3.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - ">="
24
+ - !ruby/object:Gem::Version
25
+ version: '3.0'
12
26
  - !ruby/object:Gem::Dependency
13
27
  name: pg
14
28
  requirement: !ruby/object:Gem::Requirement
@@ -196,17 +210,25 @@ files:
196
210
  - RELEASE.md
197
211
  - Rakefile
198
212
  - app/assets/javascripts/pg_sql_triggers/application.js
213
+ - app/assets/javascripts/pg_sql_triggers/trigger_actions.js
199
214
  - app/assets/stylesheets/pg_sql_triggers/application.css
215
+ - app/controllers/concerns/pg_sql_triggers/error_handling.rb
216
+ - app/controllers/concerns/pg_sql_triggers/kill_switch_protection.rb
217
+ - app/controllers/concerns/pg_sql_triggers/permission_checking.rb
200
218
  - app/controllers/pg_sql_triggers/application_controller.rb
219
+ - app/controllers/pg_sql_triggers/audit_logs_controller.rb
201
220
  - app/controllers/pg_sql_triggers/dashboard_controller.rb
202
221
  - app/controllers/pg_sql_triggers/generator_controller.rb
203
222
  - app/controllers/pg_sql_triggers/migrations_controller.rb
204
223
  - app/controllers/pg_sql_triggers/sql_capsules_controller.rb
205
224
  - app/controllers/pg_sql_triggers/tables_controller.rb
206
225
  - app/controllers/pg_sql_triggers/triggers_controller.rb
226
+ - app/helpers/pg_sql_triggers/permissions_helper.rb
207
227
  - app/models/pg_sql_triggers/application_record.rb
228
+ - app/models/pg_sql_triggers/audit_log.rb
208
229
  - app/models/pg_sql_triggers/trigger_registry.rb
209
230
  - app/views/layouts/pg_sql_triggers/application.html.erb
231
+ - app/views/pg_sql_triggers/audit_logs/index.html.erb
210
232
  - app/views/pg_sql_triggers/dashboard/index.html.erb
211
233
  - app/views/pg_sql_triggers/generator/new.html.erb
212
234
  - app/views/pg_sql_triggers/generator/preview.html.erb
@@ -223,16 +245,16 @@ files:
223
245
  - config/routes.rb
224
246
  - db/migrate/20251222000001_create_pg_sql_triggers_tables.rb
225
247
  - db/migrate/20251229071916_add_timing_to_pg_sql_triggers_registry.rb
248
+ - db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb
226
249
  - docs/README.md
227
250
  - docs/api-reference.md
251
+ - docs/audit-trail.md
228
252
  - docs/configuration.md
229
253
  - docs/getting-started.md
230
254
  - docs/kill-switch.md
231
- - docs/screenshots/.gitkeep
232
- - docs/screenshots/Generate Trigger.png
233
- - docs/screenshots/Triggers Page.png
234
- - docs/screenshots/kill error.png
235
- - docs/screenshots/kill modal for migration down.png
255
+ - docs/permissions.md
256
+ - docs/troubleshooting.md
257
+ - docs/ui-guide.md
236
258
  - docs/usage-guide.md
237
259
  - docs/web-ui.md
238
260
  - lib/generators/pg_sql_triggers/install_generator.rb
@@ -251,6 +273,7 @@ files:
251
273
  - lib/pg_sql_triggers/dsl.rb
252
274
  - lib/pg_sql_triggers/dsl/trigger_definition.rb
253
275
  - lib/pg_sql_triggers/engine.rb
276
+ - lib/pg_sql_triggers/errors.rb
254
277
  - lib/pg_sql_triggers/generator.rb
255
278
  - lib/pg_sql_triggers/generator/form.rb
256
279
  - lib/pg_sql_triggers/generator/service.rb
@@ -1 +0,0 @@
1
- # This directory is for storing screenshot images referenced in the documentation.
Binary file
Binary file
Binary file