rails-ai-bridge 3.5.2 → 3.6.1
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/CHANGELOG.md +32 -0
- data/README.md +2 -1
- data/SECURITY.md +6 -4
- data/UPGRADING.md +35 -0
- data/docs/mcp-security.md +13 -0
- data/lib/generators/rails_ai_bridge/install/install_generator.rb +1 -0
- data/lib/rails_ai_bridge/path_resolver.rb +21 -0
- data/lib/rails_ai_bridge/registry/skill_source_resolver.rb +13 -2
- data/lib/rails_ai_bridge/serializers/context_summary.rb +1 -1
- data/lib/rails_ai_bridge/version.rb +1 -1
- data/rails-ai-bridge.gemspec +2 -2
- metadata +5 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ecc139c0066902b92342f732a9e9344b5aa5468153f6193708fa95815bbe0535
|
|
4
|
+
data.tar.gz: 05fe2c9d0ada4aa7a836b1dea1ec70f60ad75a94f87c4b4ff5b29e6c4fe9ca81
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 73de5c66876b8b4ca8e7a50e3bdaaf8700984f23f884f492d7ebc880aee3fd3345efd847c4d4252012ac920c8e5450877767e79e48ecdc141f74b0d0d5dc5dd8
|
|
7
|
+
data.tar.gz: '08b0c68f5f5af762af8c87e937ba5360f5fa6732f07b3543d24bb000e118f5dad55ca4228984f7f88dc471ea70b8f3a75f8ae4b3a3dbd4eacbef205be1683cfa'
|
data/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,38 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [3.6.1] - 2026-08-07
|
|
11
|
+
|
|
12
|
+
### Security
|
|
13
|
+
|
|
14
|
+
- **Skill-pack git URL scheme allowlist** (#105/#110) — `DefaultGitRunner#clone_repo` accepts only `https://`, SCP-style `git@host:path`, and `ssh://`. Rejects `file://`, plain `http://`, and empty URLs. Validation `ArgumentError`s do not interpolate the raw URL, so credentials in userinfo cannot leak via exception messages.
|
|
15
|
+
- **SECURITY.md supported-versions table** (#106/#112) — documents 3.6.x / 3.5.x as supported, best-effort for older 3.x, and end-of-life for 1.x / 2.x.
|
|
16
|
+
- **Residual MCP HTTP risk checklist** (#107/#113) — operator checklist in `docs/mcp-security.md` (open HTTP default, CORS `*`, in-memory rate limit) with an install-generator pointer.
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- **`rubydex` bumped to `~> 0.3.0`** (#103/#111) — was `~> 0.2.9`. Run `bundle update rubydex` in host apps.
|
|
21
|
+
- **Dependency audit (2026-08)** (#99) — `bundle-audit` clean; official `mcp` remains on **0.25.x** (`< 1.0`). Migration to `mcp` 1.x remains open in #104.
|
|
22
|
+
|
|
23
|
+
## [3.6.0]
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
|
|
27
|
+
- **`mcp` minimum version raised to 0.25** (#92) — the gemspec lower bound is now `>= 0.25` (was `>= 0.10`), matching the minimum version the codebase actually requires. The upper bound remains `< 1.0`.
|
|
28
|
+
- **`rubydex` constraint tightened to `~> 0.2.9`** (#92) — was `~> 0.2.4`. This is a **minor breaking change** for users pinned to rubydex 0.2.4–0.2.8; update your lockfile with `bundle update rubydex`.
|
|
29
|
+
- **`simplecov` bumped to 1.0** (#92) — development dependency only; does not affect gem consumers. The test suite filter was migrated from `add_filter '/spec/'` to `skip 'spec'` per the simplecov 1.0 migration guide (`SourceFile#project_filename` no longer includes a leading separator).
|
|
30
|
+
|
|
31
|
+
### Fixed
|
|
32
|
+
|
|
33
|
+
- **`Style/ArrayIntersect` lint offense** (#91/#92) — pre-existing rubocop offense in `context_summary.rb` autocorrected to use `Array#intersect?`. No behavior change.
|
|
34
|
+
|
|
35
|
+
### Added
|
|
36
|
+
|
|
37
|
+
- **PathResolver architectural documentation** (#90/#91) — class-level docblock documents PathResolver's intentional role as a shared utility (11 introspector callers, high betweenness centrality). Prevents false "god class" flags from future graph analyses.
|
|
38
|
+
- **PathResolver edge-case tests** (#90/#91) — 6 new specs covering the private `SafeRelativePath` (backslash normalization, Windows path rejection, empty path rejection) and `SafeJoin` (valid joins, traversal escape prevention) helper classes.
|
|
39
|
+
|
|
8
40
|
## [3.5.2]
|
|
9
41
|
|
|
10
42
|
### Security
|
data/README.md
CHANGED
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
[](https://github.com/igmarin/rails-ai-bridge/actions)
|
|
11
11
|
[](LICENSE)
|
|
12
12
|

|
|
13
|
+
[](https://deepwiki.com/igmarin/rails-ai-bridge)
|
|
13
14
|
|
|
14
15
|
---
|
|
15
16
|
|
|
@@ -780,7 +781,7 @@ Bug reports and pull requests: [github.com/igmarin/rails-ai-bridge/issues](https
|
|
|
780
781
|
|
|
781
782
|
## Acknowledgments & Origins
|
|
782
783
|
|
|
783
|
-
This gem ships as **rails-ai-bridge** (Ruby **`RailsAiBridge`**, version **3.1
|
|
784
|
+
This gem ships as **rails-ai-bridge** (Ruby **`RailsAiBridge`**, version **3.6.1**). Earlier iterations of the same codebase were distributed as `rails-ai-context`.
|
|
784
785
|
|
|
785
786
|
RailsMCP evolved from
|
|
786
787
|
[crisnahine/rails-ai-context](https://github.com/crisnahine/rails-ai-context),
|
data/SECURITY.md
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
| Version | Supported |
|
|
6
6
|
|---------|--------------------|
|
|
7
|
-
| 3.
|
|
8
|
-
|
|
|
9
|
-
|
|
|
10
|
-
|
|
|
7
|
+
| 3.6.x | :white_check_mark: |
|
|
8
|
+
| 3.5.x | :white_check_mark: |
|
|
9
|
+
| 3.0.x–3.4.x | :white_check_mark: (security fixes best-effort) |
|
|
10
|
+
| 2.x | :x: (end of life — upgrade to 3.x) |
|
|
11
|
+
| 1.x | :x: |
|
|
12
|
+
| < 1.0 | :x: |
|
|
11
13
|
|
|
12
14
|
## Reporting a Vulnerability
|
|
13
15
|
|
data/UPGRADING.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# Upgrading rails-ai-bridge
|
|
2
2
|
|
|
3
|
+
## Upgrading from 3.6.0 to 3.6.1
|
|
4
|
+
|
|
5
|
+
**One action required if you are pinned to `rubydex` 0.2.x:**
|
|
6
|
+
|
|
7
|
+
The `rubydex` gem constraint moved from `~> 0.2.9` to `~> 0.3.0`. After upgrading
|
|
8
|
+
rails-ai-bridge:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
bundle update rubydex
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
No configuration or application code changes are required for the security and
|
|
15
|
+
documentation updates in 3.6.1. Skill-pack git sources must use `https://`,
|
|
16
|
+
SCP-style `git@host:path`, or `ssh://` (plain `http://` and `file://` are rejected).
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
## Upgrading from 3.5.x to 3.6.0
|
|
22
|
+
|
|
23
|
+
**One action required if you are pinned to an older `rubydex`:**
|
|
24
|
+
|
|
25
|
+
The `rubydex` gem constraint was tightened from `~> 0.2.4` to `~> 0.2.9`. If your
|
|
26
|
+
lockfile resolves to rubydex 0.2.4–0.2.8, update it after upgrading:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
bundle update rubydex
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
No other configuration or code changes are required. The `mcp` lower bound also
|
|
33
|
+
moved from `>= 0.10` to `>= 0.25`, but if you were already on a recent version
|
|
34
|
+
(no earlier than 0.25) this is a no-op.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
3
38
|
## Upgrading from 1.x to 2.x
|
|
4
39
|
|
|
5
40
|
**No configuration changes required.** Every `config.*` attribute from 1.x is still available — `Configuration` now delegates to focused sub-objects but exposes the same flat DSL. See `CHANGELOG.md` for the full list of internal changes.
|
data/docs/mcp-security.md
CHANGED
|
@@ -72,3 +72,16 @@ The stdio MCP server has no Bearer layer; anyone who can run the process can use
|
|
|
72
72
|
|
|
73
73
|
- [SECURITY.md](../SECURITY.md) — reporting vulnerabilities and design summary
|
|
74
74
|
- [docs/GUIDE.md](GUIDE.md) — full configuration and MCP tool reference
|
|
75
|
+
|
|
76
|
+
## Residual risk checklist (operators)
|
|
77
|
+
|
|
78
|
+
Use this before exposing HTTP MCP beyond a single-developer machine:
|
|
79
|
+
|
|
80
|
+
| Risk | Default | Mitigation |
|
|
81
|
+
|------|---------|------------|
|
|
82
|
+
| Unauthenticated HTTP when no token/resolver/JWT is configured | Open access (local DX) | Set `RAILS_AI_BRIDGE_MCP_TOKEN` or `config.http_mcp_token`, and/or `config.require_http_auth = true` |
|
|
83
|
+
| `cors_origins` includes `*` | CORS disabled unless configured | Prefer exact origins; never combine `*` with browsers on untrusted networks |
|
|
84
|
+
| In-memory rate limit | Per-process only | Use `config.mcp.rate_limiter` / reverse proxy / WAF for multi-worker or multi-host |
|
|
85
|
+
| Information disclosure via tools | Read-only tools still reveal schema/routes/code | Prefer stdio; bind HTTP to `127.0.0.1`; use exclusions/presets for regulated data |
|
|
86
|
+
|
|
87
|
+
See also [SECURITY.md](../SECURITY.md) for production `auto_mount` requirements and private vulnerability reporting.
|
|
@@ -189,6 +189,7 @@ module RailsAiBridge
|
|
|
189
189
|
# return 401 unless one of the auth mechanisms above is configured.
|
|
190
190
|
# Default is false for backward compatibility with local development.
|
|
191
191
|
# config.mcp.require_http_auth = true
|
|
192
|
+
# See docs/mcp-security.md — Residual risk checklist (operators).
|
|
192
193
|
#
|
|
193
194
|
# Timing-safe token comparison is built in, but add rate limiting too
|
|
194
195
|
# (e.g. Rack::Attack throttle on config.http_path) to prevent brute-force.
|
|
@@ -3,6 +3,27 @@
|
|
|
3
3
|
module RailsAiBridge
|
|
4
4
|
# Resolves configured Rails logical paths to filesystem paths without leaking
|
|
5
5
|
# machine-specific absolute paths into generated assistant context.
|
|
6
|
+
#
|
|
7
|
+
# == Architectural role: intentional shared utility
|
|
8
|
+
#
|
|
9
|
+
# PathResolver is deliberately used by every introspector that needs to
|
|
10
|
+
# locate files on disk (controller, model, view, stimulus, turbo, auth,
|
|
11
|
+
# api, config, action_text, activeStorage, nonArModels — 11 callers as of
|
|
12
|
+
# v3.6.1). It is NOT a god class despite high betweenness centrality in
|
|
13
|
+
# graph analyses: a foundational path-resolution utility is expected to
|
|
14
|
+
# sit at the centre of the introspector graph. Splitting it would spread
|
|
15
|
+
# path-safety logic (traversal guards, safe joins) across multiple files
|
|
16
|
+
# and weaken the single responsibility it currently holds.
|
|
17
|
+
#
|
|
18
|
+
# The three private helper classes — SafeRelativePath, SafeJoin, and
|
|
19
|
+
# ConfiguredPathsError — are kept nested and private_constant so they
|
|
20
|
+
# cannot leak into the public API or be referenced by callers. This
|
|
21
|
+
# keeps the safety surface area small and auditable in one file.
|
|
22
|
+
#
|
|
23
|
+
# If a future graph analysis flags this class again, check the
|
|
24
|
+
# betweenness centrality against the caller count before proposing a
|
|
25
|
+
# split: a utility with many callers and a single responsibility is
|
|
26
|
+
# healthy, not smelly.
|
|
6
27
|
class PathResolver
|
|
7
28
|
# Validates user-provided relative paths before filesystem operations.
|
|
8
29
|
class SafeRelativePath
|
|
@@ -69,11 +69,22 @@ module RailsAiBridge
|
|
|
69
69
|
#
|
|
70
70
|
# @param url [String] git repository URL
|
|
71
71
|
# @param dest [String] destination directory path
|
|
72
|
+
# @raise [ArgumentError] if the URL or destination is unsafe or not allowlisted
|
|
72
73
|
# @raise [RuntimeError] if git clone command fails, returns non-zero, or times out
|
|
73
74
|
# @return [void]
|
|
75
|
+
# @note Skill-pack clones accept only +https://+, SCP-style
|
|
76
|
+
# +git@host:path+, and +ssh://+ remote URLs.
|
|
77
|
+
ALLOWED_GIT_URL_PATTERN = %r{\A(?:https://|ssh://|git@[A-Za-z0-9._-]+:)}
|
|
78
|
+
|
|
74
79
|
def clone_repo(url, dest)
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
url = url.to_s
|
|
81
|
+
# Avoid interpolating +url+ into errors: userinfo may contain credentials.
|
|
82
|
+
raise ArgumentError, "Invalid git URL: URLs must not start with '-'" if url.start_with?('-')
|
|
83
|
+
raise ArgumentError, "Invalid destination: paths must not start with '-'" if dest.to_s.start_with?('-')
|
|
84
|
+
unless url.match?(ALLOWED_GIT_URL_PATTERN)
|
|
85
|
+
raise ArgumentError,
|
|
86
|
+
'Invalid git URL: scheme is not allowlisted (use https://, git@host:path, or ssh://)'
|
|
87
|
+
end
|
|
77
88
|
|
|
78
89
|
with_timeout('git clone') do
|
|
79
90
|
_stdout, stderr, status = Open3.capture3('git', 'clone', '--', url, dest)
|
|
@@ -459,7 +459,7 @@ module RailsAiBridge
|
|
|
459
459
|
private_class_method :sensitive_config_basename?
|
|
460
460
|
|
|
461
461
|
def sensitive_config_path_segment?(path)
|
|
462
|
-
path.split('/').
|
|
462
|
+
path.split('/').intersect?(SENSITIVE_CONFIG_SEGMENTS)
|
|
463
463
|
end
|
|
464
464
|
module_function :sensitive_config_path_segment?
|
|
465
465
|
private_class_method :sensitive_config_path_segment?
|
data/rails-ai-bridge.gemspec
CHANGED
|
@@ -50,11 +50,11 @@ Gem::Specification.new do |spec|
|
|
|
50
50
|
spec.require_paths = ['lib']
|
|
51
51
|
|
|
52
52
|
# Core dependencies
|
|
53
|
-
spec.add_dependency 'mcp', '>= 0.
|
|
53
|
+
spec.add_dependency 'mcp', '>= 0.25', '< 1.0' # Official MCP Ruby SDK
|
|
54
54
|
spec.add_dependency 'railties', '>= 7.1', '< 10.0'
|
|
55
55
|
spec.add_dependency 'thor', '>= 1.0', '< 3.0'
|
|
56
56
|
spec.add_dependency 'zeitwerk', '~> 2.6' # Autoloading
|
|
57
57
|
|
|
58
58
|
# Semantic code analysis via Shopify's rubydex
|
|
59
|
-
spec.add_dependency 'rubydex', '~> 0.
|
|
59
|
+
spec.add_dependency 'rubydex', '~> 0.3.0'
|
|
60
60
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rails-ai-bridge
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.6.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ismael Marin
|
|
@@ -15,7 +15,7 @@ dependencies:
|
|
|
15
15
|
requirements:
|
|
16
16
|
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '0.
|
|
18
|
+
version: '0.25'
|
|
19
19
|
- - "<"
|
|
20
20
|
- !ruby/object:Gem::Version
|
|
21
21
|
version: '1.0'
|
|
@@ -25,7 +25,7 @@ dependencies:
|
|
|
25
25
|
requirements:
|
|
26
26
|
- - ">="
|
|
27
27
|
- !ruby/object:Gem::Version
|
|
28
|
-
version: '0.
|
|
28
|
+
version: '0.25'
|
|
29
29
|
- - "<"
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '1.0'
|
|
@@ -89,14 +89,14 @@ dependencies:
|
|
|
89
89
|
requirements:
|
|
90
90
|
- - "~>"
|
|
91
91
|
- !ruby/object:Gem::Version
|
|
92
|
-
version: 0.
|
|
92
|
+
version: 0.3.0
|
|
93
93
|
type: :runtime
|
|
94
94
|
prerelease: false
|
|
95
95
|
version_requirements: !ruby/object:Gem::Requirement
|
|
96
96
|
requirements:
|
|
97
97
|
- - "~>"
|
|
98
98
|
- !ruby/object:Gem::Version
|
|
99
|
-
version: 0.
|
|
99
|
+
version: 0.3.0
|
|
100
100
|
description: Rails-AI-Bridge introspects your Rails application and exposes structure
|
|
101
101
|
to AI assistants via static context files and a live Model Context Protocol (MCP)
|
|
102
102
|
server. It classifies Active Record models semantically (Core, Join, Supporting),
|