vers 1.0.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 +7 -0
- data/CHANGELOG.md +87 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +194 -0
- data/README.md +257 -0
- data/Rakefile +248 -0
- data/SECURITY.md +164 -0
- data/VERSION-RANGE-SPEC.rst +1009 -0
- data/lib/vers/constraint.rb +158 -0
- data/lib/vers/interval.rb +229 -0
- data/lib/vers/parser.rb +447 -0
- data/lib/vers/version.rb +338 -0
- data/lib/vers/version_range.rb +173 -0
- data/lib/vers.rb +215 -0
- data/sig/vers.rbs +4 -0
- data/test-suite-data.json +335 -0
- metadata +61 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "bundler/gem_tasks"
|
|
4
|
+
require "minitest/test_task"
|
|
5
|
+
require "rdoc/task"
|
|
6
|
+
|
|
7
|
+
Minitest::TestTask.create
|
|
8
|
+
|
|
9
|
+
RDoc::Task.new do |rdoc|
|
|
10
|
+
rdoc.rdoc_dir = "doc"
|
|
11
|
+
rdoc.title = "Vers - Version Range Parser Library"
|
|
12
|
+
rdoc.main = "README.md"
|
|
13
|
+
rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
|
|
14
|
+
rdoc.options << "--line-numbers"
|
|
15
|
+
rdoc.options << "--all"
|
|
16
|
+
rdoc.options << "--charset=UTF-8"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task default: :test
|
|
20
|
+
|
|
21
|
+
namespace :spec do
|
|
22
|
+
desc "Show available VERS specification tasks"
|
|
23
|
+
task :help do
|
|
24
|
+
puts "š§ VERS Specification Tasks"
|
|
25
|
+
puts "=" * 30
|
|
26
|
+
puts "rake spec:validate_spec - Validate VERSION-RANGE-SPEC.rst is present and readable"
|
|
27
|
+
puts "rake spec:examples - Show examples of version range parsing"
|
|
28
|
+
puts "rake spec:ecosystems - Show supported package manager ecosystems"
|
|
29
|
+
puts "rake spec:compliance - Run VERS specification compliance test suite"
|
|
30
|
+
puts "rake spec:test_data - Show information about the JSON test dataset"
|
|
31
|
+
puts "rake spec:help - Show this help message"
|
|
32
|
+
puts
|
|
33
|
+
puts "Example workflow:"
|
|
34
|
+
puts " 1. rake spec:ecosystems # Review supported ecosystems"
|
|
35
|
+
puts " 2. rake test # Run full test suite"
|
|
36
|
+
puts " 3. rake spec:examples # See parsing examples"
|
|
37
|
+
puts
|
|
38
|
+
puts "The specification is stored in VERSION-RANGE-SPEC.rst at the project root."
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
desc "Validate that the VERSION-RANGE-SPEC.rst file is present and readable"
|
|
42
|
+
task :validate_spec do
|
|
43
|
+
puts "š Validating VERS Specification File..."
|
|
44
|
+
puts "=" * 50
|
|
45
|
+
|
|
46
|
+
spec_file = File.join(__dir__, "VERSION-RANGE-SPEC.rst")
|
|
47
|
+
|
|
48
|
+
if File.exist?(spec_file)
|
|
49
|
+
puts "ā
VERSION-RANGE-SPEC.rst found"
|
|
50
|
+
puts " File size: #{File.size(spec_file)} bytes"
|
|
51
|
+
puts " Last modified: #{File.mtime(spec_file)}"
|
|
52
|
+
|
|
53
|
+
# Check if file is readable and has content
|
|
54
|
+
content = File.read(spec_file)
|
|
55
|
+
if content.include?("vers:")
|
|
56
|
+
puts " Contains vers: examples: ā
"
|
|
57
|
+
else
|
|
58
|
+
puts " ā ļø File may not contain valid VERS specification content"
|
|
59
|
+
end
|
|
60
|
+
else
|
|
61
|
+
puts "ā VERSION-RANGE-SPEC.rst not found"
|
|
62
|
+
puts " Expected location: #{spec_file}"
|
|
63
|
+
exit 1
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
desc "Show examples of version range parsing for different ecosystems"
|
|
68
|
+
task :examples do
|
|
69
|
+
require_relative "lib/vers"
|
|
70
|
+
|
|
71
|
+
puts "š VERS Version Range Parsing Examples"
|
|
72
|
+
puts "=" * 50
|
|
73
|
+
|
|
74
|
+
examples = [
|
|
75
|
+
{
|
|
76
|
+
ecosystem: "npm",
|
|
77
|
+
examples: [
|
|
78
|
+
{ native: "^1.2.3", description: "Caret range (compatible within major)" },
|
|
79
|
+
{ native: "~1.2.3", description: "Tilde range (compatible within minor)" },
|
|
80
|
+
{ native: "1.2.3 - 2.3.4", description: "Hyphen range (inclusive)" },
|
|
81
|
+
{ native: ">=1.0.0 <2.0.0", description: "Space-separated constraints" }
|
|
82
|
+
]
|
|
83
|
+
},
|
|
84
|
+
{
|
|
85
|
+
ecosystem: "gem",
|
|
86
|
+
examples: [
|
|
87
|
+
{ native: "~> 1.2", description: "Pessimistic operator (compatible)" },
|
|
88
|
+
{ native: ">= 1.0, < 2.0", description: "Comma-separated constraints" }
|
|
89
|
+
]
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
ecosystem: "pypi",
|
|
93
|
+
examples: [
|
|
94
|
+
{ native: ">=1.0,<2.0", description: "Comma-separated constraints" },
|
|
95
|
+
{ native: "!=1.5.0", description: "Exclusion constraint" }
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
ecosystem: "maven",
|
|
100
|
+
examples: [
|
|
101
|
+
{ native: "[1.0,2.0]", description: "Inclusive range" },
|
|
102
|
+
{ native: "(1.0,2.0)", description: "Exclusive range" },
|
|
103
|
+
{ native: "[1.0,2.0)", description: "Mixed inclusivity" }
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
]
|
|
107
|
+
|
|
108
|
+
examples.each do |eco|
|
|
109
|
+
puts "\nš¦ #{eco[:ecosystem].upcase} Examples:"
|
|
110
|
+
puts "-" * 30
|
|
111
|
+
|
|
112
|
+
eco[:examples].each do |example|
|
|
113
|
+
begin
|
|
114
|
+
range = Vers.parse_native(example[:native], eco[:ecosystem])
|
|
115
|
+
vers_string = Vers.to_vers_string(range, eco[:ecosystem])
|
|
116
|
+
|
|
117
|
+
puts " Native: #{example[:native]}"
|
|
118
|
+
puts " VERS URI: #{vers_string}"
|
|
119
|
+
puts " Contains 1.5.0? #{range.contains?('1.5.0')}"
|
|
120
|
+
puts " Description: #{example[:description]}"
|
|
121
|
+
puts
|
|
122
|
+
rescue => e
|
|
123
|
+
puts " ā #{example[:native]} - Error: #{e.message}"
|
|
124
|
+
puts
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
desc "Show information about supported package manager ecosystems"
|
|
131
|
+
task :ecosystems do
|
|
132
|
+
require_relative "lib/vers"
|
|
133
|
+
|
|
134
|
+
puts "š Supported Package Manager Ecosystems"
|
|
135
|
+
puts "=" * 50
|
|
136
|
+
|
|
137
|
+
ecosystems = [
|
|
138
|
+
{
|
|
139
|
+
name: "npm",
|
|
140
|
+
description: "Node.js Package Manager",
|
|
141
|
+
syntax: "Caret (^), Tilde (~), Hyphen ranges",
|
|
142
|
+
examples: ["^1.2.3", "~1.2.3", "1.2.3 - 2.3.4"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
name: "gem",
|
|
146
|
+
description: "RubyGems",
|
|
147
|
+
syntax: "Pessimistic operator (~>), Standard operators",
|
|
148
|
+
examples: ["~> 1.2", ">= 1.0, < 2.0"]
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
name: "pypi",
|
|
152
|
+
description: "Python Package Index",
|
|
153
|
+
syntax: "Comma-separated constraints",
|
|
154
|
+
examples: [">=1.0,<2.0", "!=1.5.0"]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
name: "maven",
|
|
158
|
+
description: "Apache Maven (Java)",
|
|
159
|
+
syntax: "Bracket notation with inclusivity",
|
|
160
|
+
examples: ["[1.0,2.0]", "(1.0,2.0)", "[1.0,2.0)"]
|
|
161
|
+
},
|
|
162
|
+
{
|
|
163
|
+
name: "debian",
|
|
164
|
+
description: "Debian Package Manager",
|
|
165
|
+
syntax: "Standard comparison operators",
|
|
166
|
+
examples: [">=1.0.0", "<<2.0.0"]
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
name: "rpm",
|
|
170
|
+
description: "RPM Package Manager",
|
|
171
|
+
syntax: "Standard comparison operators",
|
|
172
|
+
examples: [">=1.0.0", "<=2.0.0"]
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
|
|
176
|
+
ecosystems.each do |eco|
|
|
177
|
+
puts "\nš¦ #{eco[:name].upcase}"
|
|
178
|
+
puts " Description: #{eco[:description]}"
|
|
179
|
+
puts " Syntax: #{eco[:syntax]}"
|
|
180
|
+
puts " Examples: #{eco[:examples].join(', ')}"
|
|
181
|
+
|
|
182
|
+
# Test if parsing works
|
|
183
|
+
begin
|
|
184
|
+
test_example = eco[:examples].first
|
|
185
|
+
range = Vers.parse_native(test_example, eco[:name])
|
|
186
|
+
puts " Status: ā
Parsing functional"
|
|
187
|
+
rescue => e
|
|
188
|
+
puts " Status: ā Parsing error: #{e.message}"
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
puts "\nš Summary:"
|
|
193
|
+
puts " Total ecosystems: #{ecosystems.length}"
|
|
194
|
+
puts " VERS URI format: vers:<ecosystem>/<constraints>"
|
|
195
|
+
puts " Universal operations: union, intersection, complement, exclusion"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
desc "Run VERS specification compliance test suite"
|
|
199
|
+
task :compliance do
|
|
200
|
+
puts "š§Ŗ Running VERS Specification Compliance Tests"
|
|
201
|
+
puts "=" * 50
|
|
202
|
+
|
|
203
|
+
# Run only the compliance test
|
|
204
|
+
system("ruby -Ilib:test test/test_vers_spec_compliance.rb")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
desc "Show information about the JSON test dataset"
|
|
208
|
+
task :test_data do
|
|
209
|
+
require 'json'
|
|
210
|
+
|
|
211
|
+
puts "š VERS Test Dataset Information"
|
|
212
|
+
puts "=" * 50
|
|
213
|
+
|
|
214
|
+
test_file = File.join(__dir__, "test-suite-data.json")
|
|
215
|
+
|
|
216
|
+
if File.exist?(test_file)
|
|
217
|
+
data = JSON.parse(File.read(test_file))
|
|
218
|
+
|
|
219
|
+
puts "ā
test-suite-data.json found"
|
|
220
|
+
puts " File size: #{File.size(test_file)} bytes"
|
|
221
|
+
puts " Total test cases: #{data.length}"
|
|
222
|
+
|
|
223
|
+
# Count by scheme
|
|
224
|
+
schemes = data.group_by { |test| test['scheme'] }
|
|
225
|
+
puts "\nš¦ Test cases by ecosystem:"
|
|
226
|
+
schemes.each do |scheme, tests|
|
|
227
|
+
valid_tests = tests.select { |t| !t['is_invalid'] }
|
|
228
|
+
invalid_tests = tests.select { |t| t['is_invalid'] }
|
|
229
|
+
puts " #{scheme}: #{valid_tests.length} valid, #{invalid_tests.length} invalid"
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
puts "\nš Sample test cases:"
|
|
233
|
+
data.first(3).each do |test|
|
|
234
|
+
status = test['is_invalid'] ? 'INVALID' : 'VALID'
|
|
235
|
+
puts " [#{status}] #{test['scheme']}: #{test['input']} - #{test['description']}"
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
puts "\nš” Usage:"
|
|
239
|
+
puts " This dataset can be used by other VERS implementations"
|
|
240
|
+
puts " for cross-language compatibility testing, similar to"
|
|
241
|
+
puts " the PURL project's test-suite-data.json"
|
|
242
|
+
|
|
243
|
+
else
|
|
244
|
+
puts "ā test-suite-data.json not found"
|
|
245
|
+
puts " Expected location: #{test_file}"
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
data/SECURITY.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Supported Versions
|
|
4
|
+
|
|
5
|
+
We actively support and provide security updates for the following versions:
|
|
6
|
+
|
|
7
|
+
| Version | Supported |
|
|
8
|
+
| ------- | ------------------ |
|
|
9
|
+
| 0.x.x | :white_check_mark: |
|
|
10
|
+
|
|
11
|
+
## Reporting a Vulnerability
|
|
12
|
+
|
|
13
|
+
The Vers team takes security seriously. If you discover a security vulnerability, please follow these steps:
|
|
14
|
+
|
|
15
|
+
### 1. Do NOT Create a Public Issue
|
|
16
|
+
|
|
17
|
+
Please do not report security vulnerabilities through public GitHub issues, discussions, or pull requests.
|
|
18
|
+
|
|
19
|
+
### 2. Report Privately
|
|
20
|
+
|
|
21
|
+
Send a detailed report to **andrew@ecosyste.ms** with:
|
|
22
|
+
|
|
23
|
+
- **Subject**: `[SECURITY] Vers Ruby - [Brief Description]`
|
|
24
|
+
- **Description** of the vulnerability
|
|
25
|
+
- **Steps to reproduce** the issue
|
|
26
|
+
- **Potential impact** assessment
|
|
27
|
+
- **Suggested fix** (if you have one)
|
|
28
|
+
- **Your contact information** for follow-up
|
|
29
|
+
|
|
30
|
+
### 3. What to Include
|
|
31
|
+
|
|
32
|
+
Please provide as much information as possible:
|
|
33
|
+
|
|
34
|
+
```
|
|
35
|
+
- Affected versions
|
|
36
|
+
- Attack vectors
|
|
37
|
+
- Proof of concept (if safe to share)
|
|
38
|
+
- Environmental details (Ruby version, OS, etc.)
|
|
39
|
+
- Any relevant configuration details
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Response Process
|
|
43
|
+
|
|
44
|
+
### Initial Response
|
|
45
|
+
|
|
46
|
+
- **24-48 hours**: We will acknowledge receipt of your report
|
|
47
|
+
- **Initial assessment**: Within 1 week of acknowledgment
|
|
48
|
+
- **Status updates**: Weekly until resolution
|
|
49
|
+
|
|
50
|
+
### Investigation
|
|
51
|
+
|
|
52
|
+
We will:
|
|
53
|
+
1. **Confirm** the vulnerability exists
|
|
54
|
+
2. **Assess** the severity and impact
|
|
55
|
+
3. **Develop** a fix and mitigation strategy
|
|
56
|
+
4. **Test** the fix thoroughly
|
|
57
|
+
5. **Coordinate** disclosure timeline
|
|
58
|
+
|
|
59
|
+
### Resolution
|
|
60
|
+
|
|
61
|
+
- **High/Critical**: Immediate fix and release
|
|
62
|
+
- **Medium**: Fix within 30 days
|
|
63
|
+
- **Low**: Fix in next regular release cycle
|
|
64
|
+
|
|
65
|
+
## Security Considerations
|
|
66
|
+
|
|
67
|
+
### Input Validation
|
|
68
|
+
|
|
69
|
+
The Vers library processes version strings and version range specifications:
|
|
70
|
+
|
|
71
|
+
- **Version parsing**: Validates semantic version components
|
|
72
|
+
- **Range parsing**: Handles vers URI format and native package manager syntax
|
|
73
|
+
- **Operator validation**: Ensures proper constraint operators
|
|
74
|
+
- **Regular expressions**: Used for parsing various version formats
|
|
75
|
+
|
|
76
|
+
### Potential Risk Areas
|
|
77
|
+
|
|
78
|
+
Areas that warrant security attention:
|
|
79
|
+
|
|
80
|
+
1. **Version String Parsing**: Malformed version strings could cause parsing errors
|
|
81
|
+
2. **Regular Expressions**: Complex patterns may be vulnerable to ReDoS attacks
|
|
82
|
+
3. **Range Constraint Processing**: Complex constraint combinations require validation
|
|
83
|
+
4. **Mathematical Operations**: Interval operations should handle edge cases safely
|
|
84
|
+
|
|
85
|
+
### Safe Usage Practices
|
|
86
|
+
|
|
87
|
+
When using Vers in applications:
|
|
88
|
+
|
|
89
|
+
- **Validate input**: Don't trust user-provided version strings or ranges
|
|
90
|
+
- **Handle errors**: Properly catch and handle parsing exceptions
|
|
91
|
+
- **Sanitize output**: Be careful when displaying parsed version components
|
|
92
|
+
- **Rate limiting**: If parsing many versions, implement appropriate limits
|
|
93
|
+
- **Resource limits**: Set reasonable bounds on version range complexity
|
|
94
|
+
|
|
95
|
+
## Disclosure Policy
|
|
96
|
+
|
|
97
|
+
### Coordinated Disclosure
|
|
98
|
+
|
|
99
|
+
We follow coordinated disclosure principles:
|
|
100
|
+
|
|
101
|
+
1. **Private reporting** allows us to fix issues before public disclosure
|
|
102
|
+
2. **Reasonable timeline** for fixes (typically 90 days maximum)
|
|
103
|
+
3. **Credit and recognition** for responsible reporters
|
|
104
|
+
4. **Public disclosure** after fixes are available
|
|
105
|
+
|
|
106
|
+
### Public Disclosure
|
|
107
|
+
|
|
108
|
+
After a fix is released:
|
|
109
|
+
|
|
110
|
+
1. **Security advisory** published on GitHub
|
|
111
|
+
2. **CVE requested** if applicable
|
|
112
|
+
3. **Release notes** include security information
|
|
113
|
+
4. **Community notification** through appropriate channels
|
|
114
|
+
|
|
115
|
+
## Security Updates
|
|
116
|
+
|
|
117
|
+
### Notification Channels
|
|
118
|
+
|
|
119
|
+
Security updates are announced through:
|
|
120
|
+
|
|
121
|
+
- **GitHub Security Advisories**
|
|
122
|
+
- **RubyGems security alerts**
|
|
123
|
+
- **Release notes and CHANGELOG**
|
|
124
|
+
- **Project README updates**
|
|
125
|
+
|
|
126
|
+
### Update Recommendations
|
|
127
|
+
|
|
128
|
+
To stay secure:
|
|
129
|
+
|
|
130
|
+
- **Monitor** our security advisories
|
|
131
|
+
- **Update regularly** to the latest version
|
|
132
|
+
- **Review** release notes for security fixes
|
|
133
|
+
- **Subscribe** to GitHub notifications for this repository
|
|
134
|
+
|
|
135
|
+
## Bug Bounty
|
|
136
|
+
|
|
137
|
+
Currently, we do not offer a formal bug bounty program. However, we deeply appreciate security researchers who help improve the project's security posture.
|
|
138
|
+
|
|
139
|
+
### Recognition
|
|
140
|
+
|
|
141
|
+
Contributors who responsibly disclose security issues will be:
|
|
142
|
+
|
|
143
|
+
- **Credited** in security advisories (with permission)
|
|
144
|
+
- **Mentioned** in release notes
|
|
145
|
+
- **Recognized** in project documentation
|
|
146
|
+
- **Thanked** publicly (unless anonymity is requested)
|
|
147
|
+
|
|
148
|
+
## Contact Information
|
|
149
|
+
|
|
150
|
+
**Security Contact**: andrew@ecosyste.ms
|
|
151
|
+
|
|
152
|
+
**PGP Key**: Available upon request for encrypted communications
|
|
153
|
+
|
|
154
|
+
**Response Time**: We aim to acknowledge security reports within 24-48 hours
|
|
155
|
+
|
|
156
|
+
## Additional Resources
|
|
157
|
+
|
|
158
|
+
- [VERS Specification Security Considerations](https://github.com/package-url/purl-spec/blob/main/VERSION-RANGE-SPEC.rst)
|
|
159
|
+
- [Ruby Security Best Practices](https://guides.rubyonrails.org/security.html)
|
|
160
|
+
- [OWASP Secure Coding Practices](https://owasp.org/www-project-secure-coding-practices-quick-reference-guide/)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
Thank you for helping keep Vers and its users safe!
|