spyglasses 1.0.1 → 1.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9c17daf9d91be6e696d95a82d8d55189052aa68f7d7dc01531ebecbb9fd2e924
4
- data.tar.gz: f8c66528f3fe86d414d6070544f37af1332f7a92a009eb4744c19edf84fbb309
3
+ metadata.gz: c0a3d6de667a48f878769b774eccd367018ed52f1c6628cd730e1ff8c9fdaabe
4
+ data.tar.gz: 737c8e8de705a5dc0eadf303afe1b1fa7a5d2292a700642aa5d82416565661ae
5
5
  SHA512:
6
- metadata.gz: 45eb83cc190e3b3ff8fd6851218b5d69425d8bcc8673b8f323e5d2a16ab208abf0602608eac71e7e1ab3dbb40cac300067723edc3517ee3f3b362a90ec8f0293
7
- data.tar.gz: 1cde873159cc7e46aeef4a7a15e7f72ee595886fc8eba4c501174af8b1a95431b88a064320b0efdc37a494e4b79c9286aa4cb2a5a15899568f8f7d48f072f32b
6
+ metadata.gz: 4493abc121849ba91d73c18ceaf060f0008b409bbe8c3402f74fa224c8906e6b4ea07e43e3c0f477bd028b37899db73c144ec49daabff0cce54f4878475d54a5
7
+ data.tar.gz: 22e71db5b421dcb9a78ef599261036d5b32dde80b92abb995933d57261a6b68b9a5505482fe9392c3420e363f8ff42b798c2659d2e012930e4df0d4cd97c5a41
data/CHANGELOG.md CHANGED
@@ -5,41 +5,55 @@ 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.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [1.0.1] - 2025-06-23
8
+ ## [1.1.0] - 2024-12-29
9
+
10
+ ### Fixed
11
+ - **BREAKING**: Fixed API payload format to match TypeScript collector endpoint
12
+ - Changed `platform_type` to `platformType` in JSON payload (camelCase)
13
+ - Ensured `ip_address` and `request_query` are never nil (required strings in API schema)
14
+ - Enhanced IP extraction from forwarded headers with comma-separated values
15
+ - Fixed 400 Bad Request errors when logging to collector endpoint
16
+ - Improved error handling and data validation for API compatibility
9
17
 
10
18
  ### Changed
11
- - Updated documentation links in README to point to correct docs location (https://www.spyglasses.io/docs/platforms/ruby)
12
- - Updated gem author attribution to Orchestra AI, Inc.
19
+ - **BREAKING**: JSON payload field names now use camelCase to match API expectations
20
+ - Enhanced middleware IP extraction with better fallback handling
21
+ - Improved request query string handling to ensure non-nil values
22
+
23
+ ## [1.0.1] - 2024-12-28
24
+
25
+ ### Added
26
+ - Comprehensive Ruby documentation in main docs site
27
+ - Rails-specific configuration examples
28
+ - Deployment platform guidance (Heroku, Railway, etc.)
29
+ - Troubleshooting section for common issues
30
+
31
+ ### Fixed
32
+ - Documentation formatting and code examples
33
+ - Installation instructions for various Ruby frameworks
13
34
 
14
- ## [1.0.0] - 2025-06-23
35
+ ## [1.0.0] - 2024-12-28
15
36
 
16
37
  ### Added
17
38
  - Initial release of Spyglasses Ruby gem
18
- - Core AI agent detection functionality
19
- - Bot pattern matching with regex support
20
- - AI referrer detection for platforms like ChatGPT, Claude, Perplexity
21
- - Flexible blocking system based on patterns and property settings
22
- - Rack middleware for easy integration with Ruby web frameworks
23
- - Rails, Sinatra, and generic Rack application support
24
- - Non-blocking request logging to Spyglasses collector API
25
- - Thread-safe pattern caching and background processing
26
- - Comprehensive test suite with >95% code coverage
27
- - Environment variable configuration support
39
+ - AI bot detection with pattern matching
40
+ - AI referrer detection for traffic from AI platforms
41
+ - Flexible blocking rules via Spyglasses platform
42
+ - Non-blocking request logging to collector API
43
+ - Rack middleware for universal Ruby framework support
44
+ - Thread-safe operations for concurrent applications
28
45
  - Default patterns for common AI agents and crawlers
29
- - Pattern synchronization from Spyglasses API
30
- - Debug logging capabilities
31
- - Comprehensive documentation and examples
32
-
33
- ### Security
34
- - Thread-safe operations for concurrent Ruby applications
35
- - Secure API key handling with masked logging
36
- - Input validation and error handling
37
-
38
- ### Performance
39
- - Compiled regex pattern caching
40
- - Background thread processing for API calls
41
- - Smart path exclusions for static assets
42
- - Minimal request overhead (<1ms typical)
46
+ - Configuration via environment variables
47
+ - Debug logging support
48
+ - Pattern synchronization with API
49
+ - Support for Rails, Sinatra, and other Rack-based frameworks
50
+
51
+ ### Features
52
+ - **Bot Detection**: GPTBot, ClaudeBot, ChatGPT-User, Claude-User, and more
53
+ - **AI Referrer Detection**: ChatGPT, Claude, Perplexity, Gemini, Copilot
54
+ - **Blocking Rules**: Configurable via platform dashboard
55
+ - **Performance**: Pattern caching, background logging, minimal overhead
56
+ - **Framework Support**: Universal Rack middleware design
43
57
 
44
58
  [Unreleased]: https://github.com/spyglasses/spyglasses-ruby/compare/v1.0.1...HEAD
45
59
  [1.0.1]: https://github.com/spyglasses/spyglasses-ruby/compare/v1.0.0...v1.0.1
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- spyglasses (1.0.1)
4
+ spyglasses (1.1.0)
5
5
  json (>= 2.0)
6
6
  rack (>= 2.0)
7
7
 
@@ -137,13 +137,17 @@ module Spyglasses
137
137
  def log_request_async(detection_result, request, status, response_time)
138
138
  return unless @configuration.api_key_present?
139
139
 
140
+ # Ensure ip_address is never nil
141
+ client_ip = extract_client_ip(request) || '127.0.0.1'
142
+
140
143
  request_info = {
141
144
  url: request.url,
142
145
  user_agent: request.user_agent || '',
143
- ip_address: extract_client_ip(request),
146
+ ip_address: client_ip,
144
147
  request_method: request.request_method,
145
148
  request_path: request.path,
146
- request_query: request.query_string.empty? ? nil : request.query_string,
149
+ # Ensure request_query is never nil - use empty string if no query
150
+ request_query: request.query_string || '',
147
151
  referrer: request.referrer,
148
152
  response_status: status,
149
153
  response_time_ms: (response_time * 1000).round,
@@ -157,13 +161,21 @@ module Spyglasses
157
161
 
158
162
  def extract_client_ip(request)
159
163
  # Try various headers to get the real client IP
160
- [
164
+ ip = [
161
165
  request.env['HTTP_X_FORWARDED_FOR'],
162
166
  request.env['HTTP_X_REAL_IP'],
163
167
  request.env['HTTP_CF_CONNECTING_IP'], # Cloudflare
164
168
  request.env['HTTP_X_CLIENT_IP'],
165
169
  request.env['REMOTE_ADDR']
166
- ].find { |ip| ip && !ip.empty? && ip != '127.0.0.1' } || request.ip
170
+ ].find { |ip| ip && !ip.empty? && ip != '127.0.0.1' }
171
+
172
+ # If we found an IP in headers, handle comma-separated lists (X-Forwarded-For)
173
+ if ip && ip.include?(',')
174
+ ip = ip.split(',').first.strip
175
+ end
176
+
177
+ # Return the found IP or fallback to request.ip
178
+ ip || request.ip
167
179
  end
168
180
 
169
181
  def extract_headers(request)
@@ -187,17 +187,17 @@ module Spyglasses
187
187
  {
188
188
  url: @url,
189
189
  user_agent: @user_agent,
190
- ip_address: @ip_address,
190
+ ip_address: @ip_address || '',
191
191
  request_method: @request_method,
192
192
  request_path: @request_path,
193
- request_query: @request_query,
193
+ request_query: @request_query || '',
194
194
  request_body: @request_body,
195
195
  referrer: @referrer,
196
196
  response_status: @response_status,
197
197
  response_time_ms: @response_time_ms,
198
198
  headers: @headers,
199
199
  timestamp: @timestamp,
200
- platform_type: @platform_type,
200
+ platformType: @platform_type,
201
201
  metadata: @metadata
202
202
  }
203
203
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Spyglasses
4
- VERSION = '1.0.1'
4
+ VERSION = '1.1.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spyglasses
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Orchestra AI, Inc.
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2025-06-24 00:00:00.000000000 Z
11
+ date: 2025-06-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack