pg_sql_triggers 1.2.0 → 1.4.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 (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +397 -1
  3. data/COVERAGE.md +26 -19
  4. data/GEM_ANALYSIS.md +368 -0
  5. data/Goal.md +276 -155
  6. data/README.md +45 -22
  7. data/app/assets/javascripts/pg_sql_triggers/trigger_actions.js +50 -0
  8. data/app/controllers/concerns/pg_sql_triggers/error_handling.rb +56 -0
  9. data/app/controllers/concerns/pg_sql_triggers/kill_switch_protection.rb +66 -0
  10. data/app/controllers/concerns/pg_sql_triggers/permission_checking.rb +117 -0
  11. data/app/controllers/pg_sql_triggers/application_controller.rb +10 -62
  12. data/app/controllers/pg_sql_triggers/audit_logs_controller.rb +102 -0
  13. data/app/controllers/pg_sql_triggers/dashboard_controller.rb +4 -9
  14. data/app/controllers/pg_sql_triggers/tables_controller.rb +30 -4
  15. data/app/controllers/pg_sql_triggers/triggers_controller.rb +3 -21
  16. data/app/helpers/pg_sql_triggers/permissions_helper.rb +43 -0
  17. data/app/models/pg_sql_triggers/audit_log.rb +106 -0
  18. data/app/models/pg_sql_triggers/trigger_registry.rb +218 -13
  19. data/app/views/layouts/pg_sql_triggers/application.html.erb +25 -6
  20. data/app/views/pg_sql_triggers/audit_logs/index.html.erb +177 -0
  21. data/app/views/pg_sql_triggers/dashboard/index.html.erb +34 -12
  22. data/app/views/pg_sql_triggers/tables/index.html.erb +75 -5
  23. data/app/views/pg_sql_triggers/tables/show.html.erb +17 -6
  24. data/app/views/pg_sql_triggers/triggers/_drop_modal.html.erb +16 -7
  25. data/app/views/pg_sql_triggers/triggers/_re_execute_modal.html.erb +16 -7
  26. data/app/views/pg_sql_triggers/triggers/show.html.erb +26 -6
  27. data/config/routes.rb +2 -14
  28. data/db/migrate/20260103000001_create_pg_sql_triggers_audit_log.rb +28 -0
  29. data/db/migrate/20260228000001_add_for_each_to_pg_sql_triggers_registry.rb +8 -0
  30. data/docs/README.md +15 -5
  31. data/docs/api-reference.md +233 -151
  32. data/docs/audit-trail.md +413 -0
  33. data/docs/configuration.md +28 -7
  34. data/docs/getting-started.md +17 -16
  35. data/docs/permissions.md +369 -0
  36. data/docs/troubleshooting.md +486 -0
  37. data/docs/ui-guide.md +211 -0
  38. data/docs/usage-guide.md +38 -67
  39. data/docs/web-ui.md +251 -128
  40. data/lib/generators/pg_sql_triggers/templates/trigger_dsl.rb.tt +11 -0
  41. data/lib/generators/pg_sql_triggers/templates/trigger_migration_full.rb.tt +29 -0
  42. data/lib/generators/pg_sql_triggers/trigger_generator.rb +83 -0
  43. data/lib/pg_sql_triggers/drift/db_queries.rb +12 -8
  44. data/lib/pg_sql_triggers/drift/detector.rb +51 -38
  45. data/lib/pg_sql_triggers/dsl/trigger_definition.rb +17 -23
  46. data/lib/pg_sql_triggers/engine.rb +14 -0
  47. data/lib/pg_sql_triggers/errors.rb +245 -0
  48. data/lib/pg_sql_triggers/migrator/pre_apply_comparator.rb +8 -9
  49. data/lib/pg_sql_triggers/migrator/safety_validator.rb +32 -12
  50. data/lib/pg_sql_triggers/migrator.rb +53 -6
  51. data/lib/pg_sql_triggers/permissions/checker.rb +9 -2
  52. data/lib/pg_sql_triggers/registry/manager.rb +36 -11
  53. data/lib/pg_sql_triggers/registry/validator.rb +62 -5
  54. data/lib/pg_sql_triggers/registry.rb +141 -8
  55. data/lib/pg_sql_triggers/sql/kill_switch.rb +153 -247
  56. data/lib/pg_sql_triggers/sql.rb +0 -6
  57. data/lib/pg_sql_triggers/testing/function_tester.rb +2 -0
  58. data/lib/pg_sql_triggers/version.rb +1 -1
  59. data/lib/pg_sql_triggers.rb +7 -7
  60. data/pg_sql_triggers.gemspec +53 -0
  61. metadata +35 -18
  62. data/app/controllers/pg_sql_triggers/generator_controller.rb +0 -213
  63. data/app/controllers/pg_sql_triggers/sql_capsules_controller.rb +0 -161
  64. data/app/views/pg_sql_triggers/generator/new.html.erb +0 -388
  65. data/app/views/pg_sql_triggers/generator/preview.html.erb +0 -305
  66. data/app/views/pg_sql_triggers/sql_capsules/new.html.erb +0 -81
  67. data/app/views/pg_sql_triggers/sql_capsules/show.html.erb +0 -85
  68. data/docs/screenshots/.gitkeep +0 -1
  69. data/docs/screenshots/Generate Trigger.png +0 -0
  70. data/docs/screenshots/Triggers Page.png +0 -0
  71. data/docs/screenshots/kill error.png +0 -0
  72. data/docs/screenshots/kill modal for migration down.png +0 -0
  73. data/lib/generators/trigger/migration_generator.rb +0 -60
  74. data/lib/pg_sql_triggers/generator/form.rb +0 -80
  75. data/lib/pg_sql_triggers/generator/service.rb +0 -307
  76. data/lib/pg_sql_triggers/generator.rb +0 -8
  77. data/lib/pg_sql_triggers/sql/capsule.rb +0 -79
  78. data/lib/pg_sql_triggers/sql/executor.rb +0 -200
data/docs/usage-guide.md CHANGED
@@ -15,7 +15,7 @@ PgSqlTriggers provides a Ruby DSL for defining triggers. Trigger definitions are
15
15
 
16
16
  ### Basic Trigger Definition
17
17
 
18
- Create trigger definition files in `app/triggers/`:
18
+ Create trigger definition files in `app/triggers/` (or scaffold them with the CLI generator — see below):
19
19
 
20
20
  ```ruby
21
21
  # app/triggers/users_email_validation.rb
@@ -24,11 +24,9 @@ PgSqlTriggers::DSL.pg_sql_trigger "users_email_validation" do
24
24
  on :insert, :update
25
25
  function :validate_user_email
26
26
 
27
- version 1
28
- enabled false
27
+ self.version = 1
28
+ self.enabled = true
29
29
  timing :before
30
-
31
- when_env :production
32
30
  end
33
31
  ```
34
32
 
@@ -61,25 +59,30 @@ function :validate_user_email
61
59
  Version number for tracking changes:
62
60
 
63
61
  ```ruby
64
- version 1 # Increment when trigger logic changes
62
+ self.version = 1 # Increment when trigger logic changes
65
63
  ```
66
64
 
67
65
  #### `enabled`
68
- Initial state of the trigger:
66
+ Initial state of the trigger (defaults to `true`):
69
67
 
70
68
  ```ruby
71
- enabled true # Trigger is active
72
- enabled false # Trigger is inactive
69
+ self.enabled = true # Trigger is active (default)
70
+ self.enabled = false # Trigger is inactive
73
71
  ```
74
72
 
75
- #### `when_env`
76
- Environment-specific activation:
73
+ #### `for_each_row` / `for_each_statement`
74
+ PostgreSQL execution granularity (defaults to row-level):
77
75
 
78
76
  ```ruby
79
- when_env :production # Only in production
80
- when_env :staging, :production # Multiple environments
77
+ for_each_row # FOR EACH ROW (default)
78
+ for_each_statement # FOR EACH STATEMENT
81
79
  ```
82
80
 
81
+ #### `when_env`
82
+ **Deprecated.** Environment-specific trigger declarations cause schema drift between environments.
83
+ Use application-level configuration to gate trigger behaviour by environment instead.
84
+ Calling `when_env` emits a deprecation warning and will be removed in a future major version.
85
+
83
86
  #### `timing`
84
87
  Specifies when the trigger fires relative to the event (BEFORE or AFTER):
85
88
 
@@ -97,76 +100,44 @@ PgSqlTriggers::DSL.pg_sql_trigger "orders_billing_trigger" do
97
100
  on :insert, :update
98
101
  function :calculate_order_total
99
102
 
100
- version 2
101
- enabled true
103
+ self.version = 2
104
+ self.enabled = true
102
105
  timing :after
103
-
104
- when_env :production, :staging
106
+ for_each_row
105
107
  end
106
108
  ```
107
109
 
108
110
  ## Trigger Generator
109
111
 
110
- PgSqlTriggers provides a web-based generator and Rails generators for creating trigger definitions and migrations quickly.
112
+ PgSqlTriggers provides a CLI generator that scaffolds a DSL definition and migration together from the command line.
111
113
 
112
- ### Web UI Generator
114
+ ### CLI Generator
113
115
 
114
- The web UI generator provides a user-friendly interface for creating triggers:
115
-
116
- 1. Navigate to `/pg_sql_triggers/generator/new` in your browser
117
- 2. Fill in the trigger details:
118
- - **Trigger Name**: Lowercase letters, numbers, and underscores only
119
- - **Table Name**: The PostgreSQL table to attach the trigger to
120
- - **Function Name**: The PostgreSQL function name (must match the function body)
121
- - **Timing**: When the trigger fires - BEFORE (before constraint checks) or AFTER (after constraint checks)
122
- - **Events**: Select one or more events (INSERT, UPDATE, DELETE, TRUNCATE)
123
- - **Function Body**: The complete PostgreSQL function definition
124
- - **Version**: Starting version number (default: 1)
125
- - **Enabled**: Whether the trigger should be enabled initially
126
- - **Environments**: Optional environment restrictions
127
- - **Condition**: Optional WHEN condition for the trigger
128
- 3. Preview the generated DSL and migration code (includes timing and condition display)
129
- 4. Create the trigger files
130
-
131
- The generator creates:
132
- - A DSL definition file in `app/triggers/`
133
- - A migration file in `db/triggers/`
134
- - A registry entry in the database
135
-
136
- ### Rails Generators
116
+ ```bash
117
+ rails generate pg_sql_triggers:trigger TRIGGER_NAME TABLE_NAME [EVENTS...] [--timing before|after] [--function fn_name]
118
+ ```
137
119
 
138
- You can also use Rails generators to create trigger migrations:
120
+ Example:
139
121
 
140
122
  ```bash
141
- # Generate a trigger migration
142
- rails generate trigger:migration add_user_validation
143
-
144
- # Or using the full namespace
145
- rails generate pg_sql_triggers:trigger_migration add_user_validation
123
+ rails generate pg_sql_triggers:trigger users_email_validation users insert update --timing before --function validate_user_email
146
124
  ```
147
125
 
148
- This creates a migration file in `db/triggers/` that you can edit to add your trigger logic.
126
+ This creates:
127
+ - `app/triggers/users_email_validation.rb` — DSL stub
128
+ - `db/triggers/TIMESTAMP_users_email_validation.rb` — migration with function + trigger SQL
149
129
 
150
- ### Generator Features
130
+ Files are written directly into the working tree and go through version control and code review like any other source file.
151
131
 
152
- The generator handles:
153
- - **Function Name Formatting**: Automatically quotes function names with special characters
154
- - **Multiple Environments**: Supports multiple environment restrictions
155
- - **Condition Escaping**: Properly escapes quotes in WHEN conditions
156
- - **Event Combinations**: Handles single or multiple events (INSERT, UPDATE, DELETE, TRUNCATE)
157
- - **Migration Numbering**: Automatically generates sequential migration numbers
158
- - **Error Handling**: Graceful error handling with detailed error messages
132
+ ### Migration-Only Generator
159
133
 
160
- ### Generator Edge Cases
134
+ To generate a standalone trigger migration without a DSL stub:
135
+
136
+ ```bash
137
+ rails generate pg_sql_triggers:trigger_migration add_user_validation
138
+ ```
161
139
 
162
- The generator properly handles:
163
- - Function names with special characters (quoted vs unquoted)
164
- - Multiple environments in a single trigger
165
- - Complex WHEN conditions with quotes
166
- - All event type combinations
167
- - Standalone gem usage (without Rails context)
168
- - Migration number collisions
169
- - Blank events and environments (filtered automatically)
140
+ This creates a timestamped file in `db/triggers/` that you can edit to add your trigger logic.
170
141
 
171
142
  ## Trigger Migrations
172
143
 
@@ -177,7 +148,7 @@ Trigger migrations work similarly to Rails schema migrations but are specificall
177
148
  Create a new trigger migration:
178
149
 
179
150
  ```bash
180
- rails generate trigger:migration add_validation_trigger
151
+ rails generate pg_sql_triggers:trigger_migration add_validation_trigger
181
152
  ```
182
153
 
183
154
  This creates a timestamped file in `db/triggers/`:
data/docs/web-ui.md CHANGED
@@ -8,7 +8,7 @@ The PgSqlTriggers web interface provides a visual dashboard for managing trigger
8
8
  - [Dashboard Overview](#dashboard-overview)
9
9
  - [Managing Triggers](#managing-triggers)
10
10
  - [Migration Management](#migration-management)
11
- - [SQL Capsules](#sql-capsules)
11
+ - [Audit Log](#audit-log)
12
12
  - [Permissions and Safety](#permissions-and-safety)
13
13
 
14
14
  ## Accessing the Web UI
@@ -34,11 +34,12 @@ The dashboard provides a comprehensive view of your trigger ecosystem.
34
34
 
35
35
  ### Main Features
36
36
 
37
- 1. **Trigger List**: View all triggers with their current status
37
+ 1. **Trigger List**: View all triggers with their current status and "Last Applied" timestamps
38
38
  2. **Drift Detection**: Visual indicators for drift states
39
39
  3. **Migration Status**: See pending and applied migrations
40
- 4. **Quick Actions**: Enable/disable triggers, run migrations
40
+ 4. **Quick Actions**: Enable/disable triggers, drop/re-execute triggers (based on permissions), run migrations
41
41
  5. **Kill Switch Status**: Production environment indicator
42
+ 6. **Audit Trail**: All operations are logged with actor information and viewable via Audit Log UI
42
43
 
43
44
  ![Dashboard Screenshot](screenshots/dashboard.png)
44
45
 
@@ -50,32 +51,116 @@ The dashboard provides a comprehensive view of your trigger ecosystem.
50
51
  - **○ Gray**: Disabled
51
52
  - **? Purple**: Unknown
52
53
 
54
+ ## Database Tables & Triggers
55
+
56
+ The Database Tables & Triggers page provides a comprehensive view of all tables in your database and their associated triggers. This page helps you understand which tables have triggers and which don't, making it easier to manage your trigger ecosystem.
57
+
58
+ ### Accessing the Tables Page
59
+
60
+ 1. Click "View Tables" from the dashboard
61
+ 2. Or navigate directly to `/pg_sql_triggers/tables`
62
+
63
+ ### Statistics Overview
64
+
65
+ The page displays three key statistics:
66
+ - **Tables with Triggers**: Count of tables that have at least one trigger
67
+ - **Tables without Triggers**: Count of tables that have no triggers
68
+ - **Total Tables**: Total count of all tables in the database
69
+
70
+ ### Filtering Tables
71
+
72
+ Use the filter controls to view different subsets of tables:
73
+ - **All Tables**: Shows all tables regardless of trigger status
74
+ - **With Triggers**: Shows only tables that have at least one trigger (default)
75
+ - **Without Triggers**: Shows only tables that have no triggers
76
+
77
+ The active filter is highlighted with a colored background. Click any filter button to switch views.
78
+
79
+ ### Pagination
80
+
81
+ When you have many tables, the list is paginated for better performance:
82
+ - **Default**: 20 tables per page
83
+ - **Configurable**: Choose 10, 20, 50, or 100 tables per page
84
+ - **Navigation**: Use Previous/Next buttons to move between pages
85
+ - **Filter Preservation**: Your selected filter is preserved when navigating pages
86
+
87
+ ### Table Information
88
+
89
+ Each table row displays:
90
+ - **Table Name**: The name of the database table
91
+ - **Trigger Count**: Number of triggers on the table (badge indicator)
92
+ - **Trigger Names & Functions**: List of all triggers with their function names
93
+ - Registry triggers (blue border) - Triggers managed by pg_sql_triggers
94
+ - Database-only triggers (yellow border) - Triggers not in the registry
95
+ - **Status**: Summary of enabled/disabled triggers
96
+ - **Actions**:
97
+ - "View Details" - Navigate to the table detail page
98
+ - "Create Trigger" - Scaffold a new trigger for this table using the CLI generator (see [Trigger Generator](usage-guide.md#trigger-generator))
99
+
100
+ ### Table Detail Page
101
+
102
+ Click "View Details" on any table to see:
103
+ - **Table Columns**: Complete list of columns with data types and nullability
104
+ - **Registered Triggers**: All triggers managed by pg_sql_triggers with full details
105
+ - **Database Triggers**: Triggers that exist in the database but aren't in the registry
106
+
107
+ From the table detail page, you can:
108
+ - Enable/disable individual triggers (Operator+ permission)
109
+ - Drop triggers (Admin permission)
110
+ - Re-execute drifted triggers (Admin permission)
111
+ - Create new triggers for the table
112
+
53
113
  ## Managing Triggers
54
114
 
55
115
  ### Viewing Trigger Details
56
116
 
57
- Click on any trigger to view:
58
- - Current status and drift state
117
+ Click on any trigger name (from dashboard or table view) to access the trigger detail page. The detail page includes:
118
+
119
+ #### Navigation
120
+ - **Breadcrumb Navigation**: Dashboard → Tables → Table Name → Trigger Name
121
+ - **Quick Links**: Back to Dashboard, View Table
122
+
123
+ #### Summary Panel
124
+ - Current status and drift state with visual indicators
59
125
  - Table and function information
60
- - Version history
61
- - Enabled/disabled state
62
- - Environment configuration
126
+ - Version, source (DSL/generated/manual_sql), and environment
127
+ - **Last Applied**: Human-readable timestamp showing when trigger was last applied (e.g., "2 hours ago")
128
+ - **Last Verified**: Timestamp of last drift verification
129
+ - **Created At**: Original creation timestamp
130
+
131
+ #### SQL Information
132
+ - **Function Body**: Complete PL/pgSQL function code
133
+ - **Trigger Configuration**: Events, timing, conditions
134
+ - **SQL Diff View**: If drift detected, shows expected vs actual SQL side-by-side
135
+
136
+ #### Actions
137
+ All action buttons available based on permissions:
138
+ - Enable/Disable (Operator+)
139
+ - Re-Execute (Admin, shown only when drift detected)
140
+ - Drop (Admin)
63
141
 
64
142
  ### Enabling/Disabling Triggers
65
143
 
144
+ Triggers can be enabled or disabled from multiple locations:
145
+ - **Dashboard**: Quick action buttons in the trigger table (Operator+ permission)
146
+ - **Table Detail Page**: Action buttons for each trigger (Operator+ permission)
147
+ - **Trigger Detail Page**: Full action panel (Operator+ permission)
148
+
66
149
  #### Enable a Trigger
67
150
 
68
- 1. Navigate to the trigger in the dashboard
69
- 2. Click the "Enable" button
151
+ 1. Navigate to the trigger (dashboard, table view, or trigger detail page)
152
+ 2. Click the "Enable" button (green button)
70
153
  3. In production environments, enter the confirmation text when prompted
71
- 4. Confirm the action
154
+ 4. Confirm the action in the modal
155
+ 5. The trigger will be enabled and the operation logged to the audit trail
72
156
 
73
157
  #### Disable a Trigger
74
158
 
75
- 1. Navigate to the trigger in the dashboard
76
- 2. Click the "Disable" button
159
+ 1. Navigate to the trigger (dashboard, table view, or trigger detail page)
160
+ 2. Click the "Disable" button (red button)
77
161
  3. In production environments, enter the confirmation text when prompted
78
- 4. Confirm the action
162
+ 4. Confirm the action in the modal
163
+ 5. The trigger will be disabled and the operation logged to the audit trail
79
164
 
80
165
  ### Viewing Drift Status
81
166
 
@@ -99,14 +184,18 @@ Available actions depend on trigger state and your permissions:
99
184
 
100
185
  ### Drop Trigger
101
186
 
102
- The drop action permanently removes a trigger from the database and registry.
187
+ The drop action permanently removes a trigger from the database and registry. Available from:
188
+ - **Dashboard**: "Drop" button in trigger table (Admin only)
189
+ - **Table Detail Page**: "Drop Trigger" button (Admin only)
190
+ - **Trigger Detail Page**: "Drop Trigger" button (Admin only)
103
191
 
104
- 1. Navigate to the trigger detail page
105
- 2. Click the "Drop Trigger" button
192
+ **Steps**:
193
+ 1. Navigate to the trigger (any view with drop button)
194
+ 2. Click the "Drop Trigger" button (gray button with warning icon)
106
195
  3. A modal will appear requiring:
107
196
  - **Reason**: Explanation for dropping the trigger (required for audit trail)
108
197
  - **Confirmation**: In protected environments, type the exact confirmation text shown
109
- 4. Review the warning message
198
+ 4. Review the warning message carefully
110
199
  5. Click "Drop Trigger" to confirm
111
200
 
112
201
  **Important Notes**:
@@ -115,26 +204,34 @@ The drop action permanently removes a trigger from the database and registry.
115
204
  - Protected by kill switch in production environments
116
205
  - Reason is logged for compliance and audit purposes
117
206
  - The trigger is removed from both the database and the registry
207
+ - Operation is logged to audit trail with actor information and state changes
118
208
 
119
209
  ### Re-Execute Trigger
120
210
 
121
- The re-execute action fixes drifted triggers by dropping and recreating them from the registry definition.
211
+ The re-execute action fixes drifted triggers by dropping and recreating them from the registry definition. Available from:
212
+ - **Dashboard**: "Re-Execute" button in trigger table (Admin only, shown only when drift detected)
213
+ - **Table Detail Page**: "Re-Execute Trigger" button (Admin only, shown only when drift detected)
214
+ - **Trigger Detail Page**: "Re-Execute Trigger" button (Admin only, shown only when drift detected)
122
215
 
123
- 1. Navigate to the trigger detail page
124
- 2. If the trigger is drifted, you'll see a drift warning
125
- 3. Click the "Re-Execute" button
216
+ **Steps**:
217
+ 1. Navigate to the trigger (any view with re-execute button)
218
+ 2. If the trigger is drifted, you'll see a drift warning and the "Re-Execute" button will be visible
219
+ 3. Click the "Re-Execute" button (yellow/warning button)
126
220
  4. A modal will appear showing:
127
- - **Drift Comparison**: Differences between database state and registry definition
221
+ - **Drift Comparison**: Side-by-side differences between expected (registry) and actual (database) SQL
128
222
  - **Reason Field**: Explanation for re-executing (required for audit trail)
129
223
  - **Confirmation**: In protected environments, type the exact confirmation text shown
130
- 5. Review the drift differences to understand what will change
224
+ 5. Review the drift differences carefully to understand what will change
131
225
  6. Click "Re-Execute Trigger" to confirm
132
226
 
133
227
  **What Happens**:
134
228
  1. Current trigger is dropped from the database
135
229
  2. New trigger is created using the registry definition (function_body, events, timing, condition)
136
230
  3. Registry is updated with execution timestamp
137
- 4. Operation is logged with reason and actor information
231
+ 4. Operation is logged to audit trail with:
232
+ - Reason and actor information
233
+ - Before and after state
234
+ - SQL diff information
138
235
 
139
236
  **Important Notes**:
140
237
  - Requires **Admin** permission level
@@ -142,6 +239,7 @@ The re-execute action fixes drifted triggers by dropping and recreating them fro
142
239
  - Reason is logged for compliance and audit purposes
143
240
  - Executes in a database transaction (rolls back on error)
144
241
  - Best used to fix triggers that have drifted from their DSL definition
242
+ - Button only appears when drift is detected
145
243
 
146
244
  ## Migration Management
147
245
 
@@ -204,82 +302,90 @@ After each migration action:
204
302
  - **Error**: Red flash message with error details
205
303
  - **Warnings**: Yellow flash message if issues occurred
206
304
 
207
- ## SQL Capsules
208
-
209
- SQL Capsules provide emergency escape hatches for executing SQL directly with comprehensive safety checks and audit logging.
210
-
211
- ### When to Use SQL Capsules
212
-
213
- Use SQL Capsules for:
214
- - Emergency fixes in production
215
- - Critical data corrections
216
- - Testing SQL functions
217
- - Debugging trigger behavior
218
- - One-off database operations
219
-
220
- ### Creating and Executing SQL Capsules
221
-
222
- 1. Navigate to "SQL Capsules" → "New SQL Capsule"
223
- 2. Fill in the capsule form:
224
- - **Name**: Unique identifier (alphanumeric, underscores, hyphens only)
225
- - **Environment**: Target environment (e.g., production, staging)
226
- - **Purpose**: Detailed explanation of what the SQL does and why (required for audit trail)
227
- - **SQL**: The SQL statement(s) to execute
228
- 3. Click "Create and Execute" or "Save for Later"
229
- 4. Review the capsule details on the confirmation page
230
- 5. In protected environments, enter confirmation text when prompted
231
- 6. Click "Execute" to run the SQL
232
- 7. Review the execution results
233
-
234
- ### Viewing Capsule History
235
-
236
- 1. Navigate to "SQL Capsules" → "History"
237
- 2. View list of previously executed capsules with:
238
- - Name and purpose
239
- - Environment and timestamp
240
- - SQL checksum
241
- - Execution status
242
- 3. Click on a capsule to view details
243
- 4. Re-execute historical capsules if needed
244
-
245
- ### Safety Features
246
-
247
- - **Admin Permission Required**: Only Admin users can create and execute SQL capsules
248
- - **Production Protection**: Requires typed confirmation in protected environments
249
- - **Kill Switch Integration**: All executions are protected by kill switch
250
- - **Comprehensive Logging**: All operations logged with actor, timestamp, and checksum
251
- - **Transactional Execution**: SQL runs in a transaction and rolls back on error
252
- - **Registry Storage**: All capsules are stored in the registry with checksums
253
- - **Purpose Tracking**: Required purpose field ensures all executions are documented
254
-
255
- ### Example SQL Capsules
256
-
257
- #### View All Triggers
258
- ```sql
259
- SELECT
260
- trigger_name,
261
- event_object_table,
262
- action_timing,
263
- event_manipulation
264
- FROM information_schema.triggers
265
- WHERE trigger_schema = 'public';
266
- ```
305
+ ## Audit Log
267
306
 
268
- #### Check Function Definitions
269
- ```sql
270
- SELECT
271
- routine_name,
272
- routine_type
273
- FROM information_schema.routines
274
- WHERE routine_schema = 'public'
275
- AND routine_name LIKE '%trigger%';
276
- ```
307
+ The Audit Log provides a comprehensive view of all trigger operations performed through the web UI, console APIs, and CLI. This feature is essential for compliance, debugging, and tracking changes to your trigger ecosystem.
277
308
 
278
- #### Verify Trigger State
279
- ```sql
280
- SELECT * FROM pg_sql_triggers_registry
281
- WHERE trigger_name = 'users_email_validation';
282
- ```
309
+ ### Accessing the Audit Log
310
+
311
+ 1. Navigate to the "Audit Log" link in the main navigation menu
312
+ 2. Or visit `/pg_sql_triggers/audit_logs` directly
313
+
314
+ ### Viewing Audit Log Entries
315
+
316
+ The audit log displays all operations with the following information:
317
+
318
+ - **Time**: When the operation occurred (relative time with exact timestamp on hover)
319
+ - **Trigger**: The trigger name (clickable link to trigger detail page if available)
320
+ - **Operation**: The type of operation performed (e.g., `trigger_enable`, `trigger_drop`, `trigger_re_execute`)
321
+ - **Status**: Success or failure indicator
322
+ - **Environment**: The environment where the operation was performed
323
+ - **Actor**: Who performed the operation (e.g., `UI:user_id`, `Console:email`)
324
+ - **Reason**: Explanation for the operation (for drop/re-execute operations)
325
+ - **Error**: Error message if the operation failed
326
+
327
+ ### Filtering Audit Logs
328
+
329
+ The audit log supports multiple filters to help you find specific entries:
330
+
331
+ 1. **Trigger Name**: Filter by specific trigger name
332
+ 2. **Operation**: Filter by operation type (enable, disable, drop, re_execute, etc.)
333
+ 3. **Status**: Filter by success or failure
334
+ 4. **Environment**: Filter by environment (production, staging, development, etc.)
335
+ 5. **Sort Order**: Sort by date (newest first or oldest first)
336
+
337
+ Click "Apply Filters" to update the view, or "Clear" to remove all filters.
338
+
339
+ ### Exporting Audit Logs
340
+
341
+ To export audit log entries:
342
+
343
+ 1. Apply any desired filters
344
+ 2. Click the "Export CSV" button
345
+ 3. The CSV file will include all entries matching your filters (not just the current page)
346
+ 4. File is named with timestamp: `audit_logs_YYYYMMDD_HHMMSS.csv`
347
+
348
+ The CSV export includes:
349
+ - ID, Trigger Name, Operation, Status, Environment
350
+ - Actor Type and ID
351
+ - Reason and Error Message
352
+ - Created At timestamp
353
+
354
+ ### Pagination
355
+
356
+ The audit log uses pagination to handle large datasets:
357
+
358
+ - Default: 50 entries per page (adjustable via URL parameter)
359
+ - Maximum: 200 entries per page
360
+ - Navigate using "Previous" and "Next" buttons
361
+ - Page numbers and total count displayed
362
+
363
+ ### What Gets Logged
364
+
365
+ All of the following operations are logged to the audit log:
366
+
367
+ - **Enable Trigger**: Success/failure, before/after state
368
+ - **Disable Trigger**: Success/failure, before/after state
369
+ - **Drop Trigger**: Success/failure, reason, state changes
370
+ - **Re-execute Trigger**: Success/failure, reason, drift diff information
371
+ - **Migration Operations**: Up, down, and redo operations (infrastructure ready)
372
+
373
+ Each log entry includes:
374
+ - Complete actor information (who performed the operation)
375
+ - Before and after state (for state-changing operations)
376
+ - Operation metadata (reason, confirmation text, environment)
377
+ - Error details (if the operation failed)
378
+ - Timestamp of the operation
379
+
380
+ ### Use Cases
381
+
382
+ Common use cases for the audit log:
383
+
384
+ - **Compliance**: Track all changes for audit requirements
385
+ - **Debugging**: Understand what operations were performed before an issue
386
+ - **Accountability**: See who performed specific operations
387
+ - **Troubleshooting**: Review failed operations and their error messages
388
+ - **Change History**: Track the evolution of your trigger ecosystem over time
283
389
 
284
390
  ## Permissions and Safety
285
391
 
@@ -312,7 +418,6 @@ Cannot:
312
418
  #### Admin (Full Access)
313
419
  - All Operator permissions
314
420
  - Drop triggers
315
- - Execute SQL via capsules
316
421
  - Modify registry directly
317
422
 
318
423
  ### Kill Switch Protection
@@ -322,7 +427,13 @@ In protected environments (production, staging), the Web UI enforces additional
322
427
  1. **Status Indicator**: Kill switch badge shows protection status
323
428
  2. **Confirmation Required**: Dangerous operations require typed confirmation
324
429
  3. **Warning Banners**: Visual alerts for production environment
325
- 4. **Audit Logging**: All protected operations are logged
430
+ 4. **Audit Logging**: All protected operations are logged with complete audit trail:
431
+ - Actor information (who performed the operation)
432
+ - Before and after state
433
+ - Operation details (reason, confirmation text)
434
+ - Success/failure status
435
+ - Error messages (if failed)
436
+ - Timestamp of operation
326
437
 
327
438
  ### Configuring Permissions
328
439
 
@@ -332,20 +443,26 @@ Set up custom permission checking in the initializer:
332
443
  # config/initializers/pg_sql_triggers.rb
333
444
  PgSqlTriggers.configure do |config|
334
445
  config.permission_checker = ->(actor, action, environment) {
335
- user = User.find(actor[:id])
446
+ user = User.find_by(id: actor[:id])
447
+ return false unless user
336
448
 
337
449
  case action
338
- when :view
339
- user.present?
340
- when :operate
341
- user.admin? || user.operator?
342
- when :admin
343
- user.admin?
450
+ when :view_triggers, :view_diffs
451
+ user.present? # Viewer level
452
+ when :enable_trigger, :disable_trigger, :apply_trigger, :test_trigger
453
+ user.operator? || user.admin? # Operator level
454
+ when :drop_trigger, :override_drift
455
+ user.admin? # Admin level
344
456
  else
345
457
  false
346
458
  end
347
459
  }
348
460
  end
461
+ ```else
462
+ false
463
+ end
464
+ }
465
+ end
349
466
  ```
350
467
 
351
468
  ## Screenshots
@@ -353,39 +470,45 @@ end
353
470
  ### Main Dashboard
354
471
  ![Main Dashboard](screenshots/dashboard.png)
355
472
 
356
- ### Trigger Generator
473
+ ### Migration Management
474
+ ![Migration Management](screenshots/migrations.png)
475
+
476
+ ### Kill Switch Protection
477
+ ![Kill Switch](screenshots/kill-switch.png)
357
478
 
358
- The trigger generator provides a comprehensive form for creating triggers:
479
+ ## Dashboard Enhancements (v1.3.0+)
359
480
 
360
- 1. **Basic Information**: Trigger name, table name, function name, and function body
361
- 2. **Trigger Events**: Select timing (BEFORE/AFTER) and events (INSERT, UPDATE, DELETE, TRUNCATE)
362
- 3. **Configuration**: Version, environments, WHEN condition, and enabled state
363
- 4. **Preview**: Review generated DSL and migration code with timing and condition information
481
+ ### Last Applied Column
364
482
 
365
- The preview page displays:
366
- - Generated DSL code with timing
367
- - Trigger configuration summary (timing, events, table, function, condition)
368
- - PL/pgSQL function body (editable)
369
- - SQL validation results
483
+ The dashboard now includes a "Last Applied" column showing when each trigger was last applied to the database:
484
+ - **Human-readable format**: Displays relative time (e.g., "2 hours ago", "3 days ago")
485
+ - **Tooltip**: Hover over the timestamp to see exact date and time
486
+ - **Default sorting**: Dashboard sorted by most recently applied triggers first
487
+ - **Never applied**: Shows "Never" if trigger has never been applied
370
488
 
371
- ![Trigger Generator](screenshots/generator.png)
489
+ This helps you quickly identify:
490
+ - Which triggers are actively maintained
491
+ - How recently triggers were updated
492
+ - Triggers that may need attention
372
493
 
373
- ### Migration Management
374
- ![Migration Management](screenshots/migrations.png)
494
+ ### Quick Actions in Dashboard
375
495
 
376
- ### Kill Switch Protection
377
- ![Kill Switch](screenshots/kill-switch.png)
496
+ The dashboard trigger table now includes quick action buttons:
497
+ - **Enable/Disable**: Toggle trigger state (Operator+ permission)
498
+ - **Drop**: Remove trigger permanently (Admin only)
499
+ - **Re-Execute**: Fix drifted triggers (Admin only, shown only when drift detected)
378
500
 
379
- ### SQL Capsules
380
- ![SQL Capsules](screenshots/sql-capsules.png)
501
+ All actions respect permission levels and show/hide buttons based on your role.
381
502
 
382
503
  ## Tips and Best Practices
383
504
 
384
505
  1. **Check Status Regularly**: Monitor drift detection to catch unexpected changes
385
506
  2. **Use Confirmations**: Don't bypass production confirmations without understanding the impact
386
507
  3. **Test in Development**: Always test UI actions in development before production
387
- 4. **Review Logs**: Check application logs after important operations
388
- 5. **Document Changes**: Add comments when making manual changes via SQL Capsules
508
+ 4. **Review Logs**: Check application logs and audit trail after important operations
509
+ 5. **Document Changes**: Add detailed reasons when dropping or re-executing triggers
510
+ 6. **Monitor Last Applied**: Use the "Last Applied" column to track trigger maintenance activity
511
+ 7. **Breadcrumb Navigation**: Use breadcrumbs on trigger detail page for easy navigation
389
512
 
390
513
  ## Troubleshooting
391
514