rails-informant 0.0.5 → 0.0.6
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/README.md +43 -33
- data/exe/informant-mcp +1 -5
- data/lib/generators/rails_informant/install_generator.rb +38 -0
- data/lib/generators/rails_informant/skill/templates/SKILL.md +1 -1
- data/lib/generators/rails_informant/templates/create_informant_tables.rb.erb +7 -7
- data/lib/generators/rails_informant/templates/initializer.rb.erb +1 -1
- data/lib/rails_informant/engine.rb +12 -6
- metadata +21 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 51a0bd3a42b6c332ee192a319eaf43b8b129013995ac42d35a0de294a69c968f
|
|
4
|
+
data.tar.gz: 2eef05b3963d12586672b650cff43f5b999d8852ff229e42114f6b9cff0572a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b9e51bc32c5393a1dced3621b661c72e8dcdf87d11a5d640c7addceb1ce9ec1526bc170519d0e71466503e2d589d53bdaec3b8063c21020d7fff3c6db5f12b82
|
|
7
|
+
data.tar.gz: 5eff7c322d4722b26d018dcf7a12e8f692e57e0f66374612e27271b41766a142cde8bb116dedbab1594f77aa6b1e28ec0e1b586929c69c39a9bd68b5f20cd2e3
|
data/README.md
CHANGED
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
<p>
|
|
14
14
|
<a href="#why-rails-informant">Why Rails Informant?</a>
|
|
15
15
|
◆ <a href="#quick-start">Quick Start</a>
|
|
16
|
+
◆ <a href="#agent-setup">Agent Setup</a>
|
|
16
17
|
◆ <a href="#configuration">Configuration</a>
|
|
17
18
|
◆ <a href="#mcp-server">MCP Server</a>
|
|
18
19
|
◆ <a href="#architecture">Architecture</a>
|
|
19
|
-
◆ <a href="#data
|
|
20
|
+
◆ <a href="#data-and-privacy">Data and Privacy</a>
|
|
20
21
|
◆ <a href="#security">Security</a>
|
|
21
22
|
</p>
|
|
22
23
|
</div>
|
|
@@ -65,6 +66,38 @@ Errors are captured automatically in non-local environments. To capture errors m
|
|
|
65
66
|
RailsInformant.capture(exception, context: { order_id: 42 })
|
|
66
67
|
```
|
|
67
68
|
|
|
69
|
+
## Agent Setup
|
|
70
|
+
|
|
71
|
+
End-to-end path for AI agents (Claude Code, Devin) to start triaging errors:
|
|
72
|
+
|
|
73
|
+
1. **Install the gem** -- follow [Quick Start](#quick-start) above
|
|
74
|
+
2. **Set an authentication token** in your Rails credentials or env var:
|
|
75
|
+
```ruby
|
|
76
|
+
# config/initializers/rails_informant.rb
|
|
77
|
+
config.api_token = Rails.application.credentials.dig(:rails_informant, :api_token)
|
|
78
|
+
```
|
|
79
|
+
3. **Add the MCP server** to your agent's config (see [MCP Server](#mcp-server) for full options):
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"mcpServers": {
|
|
83
|
+
"informant": {
|
|
84
|
+
"command": "informant-mcp",
|
|
85
|
+
"env": {
|
|
86
|
+
"INFORMANT_PRODUCTION_URL": "https://myapp.com",
|
|
87
|
+
"INFORMANT_PRODUCTION_TOKEN": "your-api-token"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
4. **Install the Claude Code skill** (optional but recommended):
|
|
94
|
+
```sh
|
|
95
|
+
bin/rails generate rails_informant:skill
|
|
96
|
+
```
|
|
97
|
+
5. **Use `/informant`** in Claude Code to triage and fix errors, or let Devin handle them autonomously with the [Devin integration](#devin-ai).
|
|
98
|
+
|
|
99
|
+
> **Env var scoping:** `INFORMANT_API_TOKEN` configures the Rails app. `INFORMANT_PRODUCTION_URL` and `INFORMANT_PRODUCTION_TOKEN` configure the MCP server (agent side). They are different processes -- both need a token, but the MCP env vars point the agent at your running app.
|
|
100
|
+
|
|
68
101
|
## Configuration
|
|
69
102
|
|
|
70
103
|
```ruby
|
|
@@ -77,11 +110,11 @@ RailsInformant.configure do |config|
|
|
|
77
110
|
end
|
|
78
111
|
```
|
|
79
112
|
|
|
80
|
-
Every option can be set via an environment variable. The initializer takes precedence over env vars.
|
|
113
|
+
Every option can be set via an environment variable. The initializer takes precedence over env vars. These configure the **Rails app**. For MCP server env vars (agent side), see [Agent Setup](#agent-setup).
|
|
81
114
|
|
|
82
115
|
| Option | Env var | Default | Description |
|
|
83
116
|
|--------|---------|---------|-------------|
|
|
84
|
-
| `api_token` | `INFORMANT_API_TOKEN` | `nil` |
|
|
117
|
+
| `api_token` | `INFORMANT_API_TOKEN` | `nil` | Authentication token for MCP server access |
|
|
85
118
|
| `capture_errors` | `INFORMANT_CAPTURE_ERRORS` | `true` | Enable/disable error capture (set to `"false"` to disable) |
|
|
86
119
|
| `devin_api_key` | `INFORMANT_DEVIN_API_KEY` | `nil` | Devin AI API key for autonomous error fixing |
|
|
87
120
|
| `devin_playbook_id` | `INFORMANT_DEVIN_PLAYBOOK_ID` | `nil` | Devin playbook ID for error triage workflow |
|
|
@@ -114,33 +147,10 @@ config.ignored_exceptions = ["MyApp::BoringError", /Stripe::/]
|
|
|
114
147
|
|
|
115
148
|
Structured events from `ActiveSupport::Notifications` are captured automatically as breadcrumbs -- SQL query names, cache hits, template renders, HTTP calls, job executions. Stored per-occurrence for rich debugging context without raw log lines.
|
|
116
149
|
|
|
117
|
-
## API
|
|
118
|
-
|
|
119
|
-
Token-authenticated JSON API mounted at `/informant/api/v1/`.
|
|
120
|
-
|
|
121
|
-
```text
|
|
122
|
-
GET /informant/api/v1/errors # List error groups (paginated, filterable)
|
|
123
|
-
GET /informant/api/v1/errors/:id # Show with recent occurrences
|
|
124
|
-
PATCH /informant/api/v1/errors/:id # Update status or notes
|
|
125
|
-
DELETE /informant/api/v1/errors/:id # Delete group and occurrences
|
|
126
|
-
PATCH /informant/api/v1/errors/:id/fix_pending # Mark fix pending
|
|
127
|
-
PATCH /informant/api/v1/errors/:id/duplicate # Mark as duplicate
|
|
128
|
-
GET /informant/api/v1/occurrences # List occurrences
|
|
129
|
-
GET /informant/api/v1/status # Error monitoring summary
|
|
130
|
-
```
|
|
131
|
-
|
|
132
|
-
Authenticate with `Authorization: Bearer <token>`.
|
|
133
|
-
|
|
134
150
|
## MCP Server
|
|
135
151
|
|
|
136
152
|
The bundled `informant-mcp` executable connects Claude Code to your error data via [Model Context Protocol (MCP)](https://modelcontextprotocol.io).
|
|
137
153
|
|
|
138
|
-
The MCP server requires the `mcp` gem, which is not a runtime dependency. Add it to your Gemfile:
|
|
139
|
-
|
|
140
|
-
```ruby
|
|
141
|
-
gem "mcp", ">= 0.7", "< 2"
|
|
142
|
-
```
|
|
143
|
-
|
|
144
154
|
### Setup
|
|
145
155
|
|
|
146
156
|
Add to your Claude Code MCP config:
|
|
@@ -233,12 +243,12 @@ The notification prompt includes: error class, error message (truncated), severi
|
|
|
233
243
|
Development Machine Remote Servers
|
|
234
244
|
+-----------------------+ +-----------------------+
|
|
235
245
|
| Claude Code | | Production |
|
|
236
|
-
| | | | /informant
|
|
246
|
+
| | | | /informant |
|
|
237
247
|
| | stdio | +-----------------------+
|
|
238
248
|
| v | HTTPS+Token
|
|
239
249
|
| MCP Server | -----------> +-----------------------+
|
|
240
250
|
| (exe/informant-mcp) | | Staging |
|
|
241
|
-
| | | /informant
|
|
251
|
+
| | | /informant |
|
|
242
252
|
+-----------------------+ +-----------------------+
|
|
243
253
|
|
|
244
254
|
Inside the Rails app:
|
|
@@ -288,7 +298,7 @@ bin/rails informant:stats # Show error monitoring statistics
|
|
|
288
298
|
bin/rails informant:purge # Purge resolved errors older than retention_days
|
|
289
299
|
```
|
|
290
300
|
|
|
291
|
-
## Data
|
|
301
|
+
## Data and Privacy
|
|
292
302
|
|
|
293
303
|
Each occurrence stores the following PII:
|
|
294
304
|
|
|
@@ -314,18 +324,18 @@ This replaces email values with `[FILTERED]` in occurrence data. IP addresses ca
|
|
|
314
324
|
|
|
315
325
|
## Security
|
|
316
326
|
|
|
317
|
-
-
|
|
327
|
+
- MCP server requires token authentication (`secure_compare`)
|
|
318
328
|
- All stored context is filtered through `ActiveSupport::ParameterFilter`
|
|
319
329
|
- MCP server enforces HTTPS by default
|
|
320
330
|
- Security headers: `Cache-Control: no-store`, `X-Content-Type-Options: nosniff`
|
|
321
331
|
- Error capture never breaks the host application
|
|
322
332
|
- Webhook payloads strip PII by default
|
|
323
|
-
- **Rate limiting** -- the
|
|
333
|
+
- **Rate limiting** -- the engine does not include built-in rate limiting. Add rate limiting on the `/informant/` prefix in production, for example with [Rack::Attack](https://github.com/rack/rack-attack):
|
|
324
334
|
|
|
325
335
|
```ruby
|
|
326
336
|
# config/initializers/rack_attack.rb
|
|
327
|
-
Rack::Attack.throttle("informant
|
|
328
|
-
req.ip if req.path.start_with?("/informant/
|
|
337
|
+
Rack::Attack.throttle("informant", limit: 60, period: 1.minute) do |req|
|
|
338
|
+
req.ip if req.path.start_with?("/informant/")
|
|
329
339
|
end
|
|
330
340
|
```
|
|
331
341
|
|
data/exe/informant-mcp
CHANGED
|
@@ -3,11 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
require "mcp"
|
|
8
|
-
rescue LoadError
|
|
9
|
-
abort 'The "mcp" gem is required to run the Informant MCP server. Add gem "mcp", ">= 0.7", "< 2" to your Gemfile and run bundle install.'
|
|
10
|
-
end
|
|
6
|
+
require "mcp"
|
|
11
7
|
|
|
12
8
|
require "optparse"
|
|
13
9
|
require "rails_informant/mcp"
|
|
@@ -20,5 +20,43 @@ module RailsInformant
|
|
|
20
20
|
def mount_engine
|
|
21
21
|
route "mount RailsInformant::Engine => '/informant'"
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
def print_next_steps
|
|
25
|
+
say ""
|
|
26
|
+
say "Rails Informant installed!", :green
|
|
27
|
+
say ""
|
|
28
|
+
say "Next steps:", :yellow
|
|
29
|
+
say " 1. Run migrations:"
|
|
30
|
+
say " bin/rails db:migrate"
|
|
31
|
+
say ""
|
|
32
|
+
say " 2. Set a token (required for MCP server access):"
|
|
33
|
+
say " bin/rails credentials:edit"
|
|
34
|
+
say " # Add: rails_informant:"
|
|
35
|
+
say " # api_token: #{SecureRandom.hex 32}"
|
|
36
|
+
say ""
|
|
37
|
+
say " 3. Add the MCP server to .mcp.json (for Claude Code):"
|
|
38
|
+
say " {"
|
|
39
|
+
say " \"mcpServers\": {"
|
|
40
|
+
say " \"informant\": {"
|
|
41
|
+
say " \"command\": \"informant-mcp\","
|
|
42
|
+
say " \"env\": {"
|
|
43
|
+
say " \"INFORMANT_PRODUCTION_URL\": \"https://your-app.com\","
|
|
44
|
+
say " \"INFORMANT_PRODUCTION_TOKEN\": \"your-api-token\""
|
|
45
|
+
say " }"
|
|
46
|
+
say " }"
|
|
47
|
+
say " }"
|
|
48
|
+
say " }"
|
|
49
|
+
say ""
|
|
50
|
+
say " 4. Optional — install the Claude Code skill:"
|
|
51
|
+
say " bin/rails generate rails_informant:skill"
|
|
52
|
+
say ""
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def json_column_type
|
|
58
|
+
adapter = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).first&.adapter.to_s
|
|
59
|
+
adapter.match?(/postgres/i) ? "jsonb" : "json"
|
|
60
|
+
end
|
|
23
61
|
end
|
|
24
62
|
end
|
|
@@ -38,13 +38,13 @@ class CreateInformantTables < ActiveRecord::Migration[8.1]
|
|
|
38
38
|
create_table :informant_occurrences do |t|
|
|
39
39
|
t.references :error_group, null: false,
|
|
40
40
|
foreign_key: { to_table: :informant_error_groups }
|
|
41
|
-
t
|
|
42
|
-
t
|
|
43
|
-
t
|
|
44
|
-
t
|
|
45
|
-
t
|
|
46
|
-
t
|
|
47
|
-
t
|
|
41
|
+
t.<%= json_column_type %> :backtrace
|
|
42
|
+
t.<%= json_column_type %> :exception_chain
|
|
43
|
+
t.<%= json_column_type %> :request_context
|
|
44
|
+
t.<%= json_column_type %> :user_context
|
|
45
|
+
t.<%= json_column_type %> :custom_context
|
|
46
|
+
t.<%= json_column_type %> :environment_context
|
|
47
|
+
t.<%= json_column_type %> :breadcrumbs
|
|
48
48
|
t.string :git_sha
|
|
49
49
|
t.timestamps
|
|
50
50
|
|
|
@@ -15,7 +15,7 @@ RailsInformant.configure do |config|
|
|
|
15
15
|
# Or override what is captured by setting user context explicitly:
|
|
16
16
|
# RailsInformant::Current.user_context = { id: current_user.id }
|
|
17
17
|
|
|
18
|
-
#
|
|
18
|
+
# Authentication token (required for MCP server access)
|
|
19
19
|
config.api_token = Rails.application.credentials.dig(:rails_informant, :api_token)
|
|
20
20
|
|
|
21
21
|
# Slack webhook URL for error notifications
|
|
@@ -68,19 +68,25 @@ module RailsInformant
|
|
|
68
68
|
|
|
69
69
|
token = RailsInformant.api_token
|
|
70
70
|
|
|
71
|
-
if token.nil?
|
|
72
|
-
|
|
71
|
+
message = if token.nil?
|
|
72
|
+
<<~MSG.squish
|
|
73
73
|
RailsInformant: api_token must be configured when capture_errors is enabled.
|
|
74
74
|
Set it in your initializer: config.api_token = "your-secret-token"
|
|
75
75
|
MSG
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
if token.length < MINIMUM_TOKEN_LENGTH
|
|
79
|
-
raise <<~MSG.squish
|
|
76
|
+
elsif token.length < MINIMUM_TOKEN_LENGTH
|
|
77
|
+
<<~MSG.squish
|
|
80
78
|
RailsInformant: api_token must be at least #{MINIMUM_TOKEN_LENGTH} characters.
|
|
81
79
|
Use SecureRandom.hex(32) or Rails credentials to generate a secure token.
|
|
82
80
|
MSG
|
|
83
81
|
end
|
|
82
|
+
|
|
83
|
+
return unless message
|
|
84
|
+
|
|
85
|
+
if RailsInformant.server_mode?
|
|
86
|
+
raise message
|
|
87
|
+
else
|
|
88
|
+
Rails.logger&.warn message
|
|
89
|
+
end
|
|
84
90
|
end
|
|
85
91
|
end
|
|
86
92
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-informant
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Daniel López Prat
|
|
@@ -65,6 +65,26 @@ dependencies:
|
|
|
65
65
|
- - ">="
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '8.1'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: mcp
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0.7'
|
|
75
|
+
- - "<"
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '2'
|
|
78
|
+
type: :runtime
|
|
79
|
+
prerelease: false
|
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
81
|
+
requirements:
|
|
82
|
+
- - ">="
|
|
83
|
+
- !ruby/object:Gem::Version
|
|
84
|
+
version: '0.7'
|
|
85
|
+
- - "<"
|
|
86
|
+
- !ruby/object:Gem::Version
|
|
87
|
+
version: '2'
|
|
68
88
|
- !ruby/object:Gem::Dependency
|
|
69
89
|
name: railties
|
|
70
90
|
requirement: !ruby/object:Gem::Requirement
|