net-connector 0.19.0 → 0.21.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: fe3f1f3bc71cf02e0007ec892699ea03fb13f30b697f5e318ca256159e77a466
4
- data.tar.gz: 7f2ed60b91541c0eb362b1dc1c063661f5f22eac07719f1ed9d56f552a7d175b
3
+ metadata.gz: 7e379dbe5598c3f170fdcfbc123103c4eb178941508e8fa0df12e2b8043fdf93
4
+ data.tar.gz: 3ad7934b5aa811031ea1a1283c67743494795472a0361207869d6b16d03cfda0
5
5
  SHA512:
6
- metadata.gz: 03ea333dc6fdc10956b58478de7b67d8e3061345b3d96af8601a847dd393b158cd0bdbd7e4ca3ebc69c7cdca03d58ced76e34964b0370d9b2b0dad27c4d1f9dc
7
- data.tar.gz: 38784dee207a4b5161add61183ebb49cf7b4a7a843171a29da2effe393105cd9c4bd00f2a0d3780ab296c430149a43792c85b9054375cb1c97269e89b1ad7f96
6
+ metadata.gz: 07e68bd1ebd341839e6c45db6e821e76f8371c7b5d2e135a064925be5ca6f0d06189cf22be97fd2d8ea676fc542216dc67bfeff88fd06043b310fe72e642b67b
7
+ data.tar.gz: 96400e19508ca207d0e4aeccb0dc5aad7529bafebb0e2a4723a10e9d3907e07c5ba9f722afaabf5d78f257184f2b7f27aab82da91c7e64f60ca005188d1aa445
data/CHANGELOG.md CHANGED
@@ -2,6 +2,18 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.21.0 - 2026-10-30
6
+
7
+ - Rename neighbor fields to `remote_name`, `remote_interface` and `remote_chassis_id`, retaining `local_interface`. Collection progress reads schema 4 `target`; require ctx_cli 0.5. No legacy accessor aliases.
8
+
9
+ ## 0.20.0 - 2026-10-29
10
+
11
+ - Require the latest stable TextFSM 0.5.1, align the minimum dependency matrix, and verify JSON 3 with its original published package instead of a source metadata patch.
12
+
13
+ - Recheck streamed archive content on the pinned descriptor so same-timestamp overwrites cannot receive a successful copy or delivery receipt.
14
+
15
+ - Bound compatible ctx_cli and expect-pty dependencies to the contract versions tested with this release (ctx_cli 0.4.x and expect-pty 0.9.6 through 0.9.x).
16
+
5
17
  ## 0.19.0 - 2026-10-29
6
18
 
7
19
  - Extract `Netdisco::Catalog#devices(policy:)` for immutable inventory without credentials or operations; Fleet delegates inventory access. Add live, injected `Credentials#resolve(platform:)` with platform-specific username/password/enable-password precedence and independent secret snapshots.
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  Ruby sessions for network device CLIs over SSH or Telnet. Collect configurations, save private backups, run interactive scripts, parse output with TextFSM, and back up fleets from Netdisco inventories.
6
6
 
7
- Requires Ruby 3.4+, expect-pty 0.9.4+ and a POSIX system. SSH uses local OpenSSH; Telnet requires a local `telnet` executable and explicit configuration.
7
+ Requires Ruby 3.4+, expect-pty 0.9.6+, ctx_cli 0.4.x, TextFSM 0.5.1+ and a POSIX system. SSH uses local OpenSSH; Telnet requires a local `telnet` executable and explicit configuration.
8
8
 
9
9
  ## Install
10
10
 
@@ -85,3 +85,7 @@ credentials = Net::Connector::Credentials.new(env: ENV).resolve(platform: :cisco
85
85
  Catalog owns inventory reading, normalization, duplicate marking and cache status (`#status`). It does not resolve device credentials, log into devices or create operation reports. Pass one policy snapshot throughout a run. Fleet delegates to Catalog and retains operation orchestration.
86
86
 
87
87
  Credentials reads the injected environment on every `resolve`; it returns an independent frozen hash, or nil when no username is available. Platform-specific `NC_<PLATFORM>_USERNAME`, `_PASSWORD`, and `_ENABLE_PASSWORD` override `NC_DEVICE_USERNAME`, `NC_DEVICE_PASSWORD`, and `NC_ENABLE_PASSWORD` respectively. Blank values fall back. Secrets are never cached or included in object inspection.
88
+
89
+ ## Domain contract migration (2026-10-30)
90
+
91
+ Rename neighbor fields to `remote_name`, `remote_interface` and `remote_chassis_id`, retaining `local_interface`. Collection progress reads schema 4 `target`; require ctx_cli 0.5. No legacy accessor aliases. See the [schema 4 migration and module contracts](https://github.com/gatework/ctx_runner/blob/main/docs/contracts-2026-10-30.md). Regenerate old collection reports and change plans; changing only their version number is not supported.
data/README.zh-CN.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  通过 SSH 或 Telnet 操作网络设备的 Ruby 库。支持配置采集、私有备份、交互脚本、TextFSM 解析,以及基于 Netdisco 清单的批量备份。
6
6
 
7
- 需要 Ruby 3.4+、expect-pty 0.9.4+ 和 POSIX 系统。SSH 使用本机 OpenSSH;Telnet 需要本机安装 `telnet` 并显式配置。
7
+ 需要 Ruby 3.4+、expect-pty 0.9.6+、ctx_cli 0.4.x、TextFSM 0.5.1+ 和 POSIX 系统。SSH 使用本机 OpenSSH;Telnet 需要本机安装 `telnet` 并显式配置。
8
8
 
9
9
  ## 安装
10
10
 
data/docs/VERIFICATION.md CHANGED
@@ -155,7 +155,7 @@ SHA-256,首次使用时从官方 GitHub Release 下载,缓存到 `tmp/tools/
155
155
 
156
156
  运行依赖写在 `net-connector.gemspec`,包括直接使用的、可能从 Ruby 默认
157
157
  安装中拆出的标准库 gem。开发工具只写在 Gemfile,不进入运行依赖。
158
- PTY 与共享脱敏直接依赖 expect-pty 0.9.4+ 的公开 `Session`、`buffer_bytesize` 和 `Expect::Redactor` 接口。
158
+ PTY 与共享脱敏直接依赖 expect-pty 0.9.6+ 的公开 `Session`、`buffer_bytesize` 和 `Expect::Redactor` 接口。
159
159
  开发用 `parallel` 保持 1.x。升级 expect-pty 时先验证源码集成,再用本次构建的 gem 验证隔离安装;
160
160
  新依赖版本发布前不得将本地构建验证记成已发布版本验收,也不能退回旧接口掩盖依赖缺失。
161
161
 
@@ -163,7 +163,7 @@ PTY 与共享脱敏直接依赖 expect-pty 0.9.4+ 的公开 `Session`、`buffer_
163
163
  分别解析兼容依赖。应用使用者应在自己的应用中提交 lockfile。测试和打包
164
164
  脚本通过隔离安装检查运行依赖,避免依赖开发环境里偶然存在的 gem。
165
165
 
166
- `gemfiles/minimum.gemfile` 固定受支持的依赖下界 expect-pty 0.9.4、textfsm 0.2.0;
166
+ `gemfiles/minimum.gemfile` 固定受支持的依赖下界 expect-pty 0.9.6、ctx_cli 0.4.0、textfsm 0.5.1;
167
167
  标准库和开发工具仍按主 Gemfile 的兼容范围解析。普通矩阵检查允许版本的正常解析,
168
168
  另在 Ubuntu / Ruby 3.4、4.0 检查这组版本的全量测试与隔离安装。本地复现:
169
169
 
@@ -206,17 +206,16 @@ Gitleaks 默认规则之外,还检查网络设备密码/SNMP community 配置
206
206
  扫描工具不会自动改写 Git 历史或真实设备备份。规则用于拦截常见泄露,
207
207
  发布前仍需人工确认设备名称、拓扑和业务配置等上下文信息是否适合公开。
208
208
 
209
- ## JSON 2 发布依赖与 JSON 3 源码兼容分开验证
209
+ ## 使用已发布 TextFSM 分别验证 JSON 2 与 JSON 3
210
210
 
211
- 默认及最低依赖任务验证实际发布依赖。TextFSM 0.2.0 的公开声明仍为 `json ~> 2.0`;
212
- 本地同版本 gem 的修订不能证明普通消费者能安装 JSON 3。
211
+ 运行依赖要求 TextFSM 0.5.1 或更新版本;0.5.1 的公开 JSON 声明为 `>= 2.0`,
212
+ 允许普通消费者选择 JSON 2 或 JSON 3。最低依赖任务固定 TextFSM 0.5.1 与 JSON 2。
213
213
 
214
- CI 的 `json3-source-compatibility` 在 Ruby 3.4 / 4.0 检出固定 TextFSM commit
215
- `733340de378f2d7fbe530b48f2cf1dd6c30c69b0`,应用仓库内
216
- `script/compatibility/textfsm-json3.patch`,只放宽依赖声明,再执行完整测试和真实打包隔离安装。
217
- 该任务明确代表尚未发布依赖声明下的源码兼容性;不自动发布、替换正式依赖或修改用户的全局 gem。
214
+ CI 的 `json3-compatibility` 在 Ruby 3.4 / 4.0 使用已发布 TextFSM 0.5.1 与 JSON 3,
215
+ 执行完整测试和真实打包隔离安装。脚本核对原始 gem 的 JSON 依赖声明,再将发布包缓存
216
+ 交给隔离消费者;不再检出旧源码、修改 metadata 或重建同版本 TextFSM。
218
217
 
219
- 复现时,在 `tmp/json3/textfsm` 准备该源码并应用补丁,然后运行:
218
+ 本地复现:
220
219
 
221
220
  ```sh
222
221
  BUNDLE_GEMFILE=gemfiles/json3.gemfile bundle install
data/docs/usage.md CHANGED
@@ -165,6 +165,6 @@ Per-command prompts use `interactions: [Net::Connector::Interaction.new(/Token:\
165
165
 
166
166
  ## Dependencies and extensions
167
167
 
168
- Load device APIs with `require "net/connector"`; Netdisco has a separate entrypoint. Vendor implementations and TextFSM load on demand. The gemspec requires expect-pty 0.9.4+; the host application's lockfile selects concrete dependency versions. The minimum dependency matrix uses TextFSM 0.2.0 and JSON 2, with a separate fixed-source TextFSM patch matrix for JSON 3.
168
+ Load device APIs with `require "net/connector"`; Netdisco has a separate entrypoint. Vendor implementations and TextFSM load on demand. The gemspec requires expect-pty 0.9.6+, ctx_cli 0.4.x and TextFSM 0.5.1+; the host application's lockfile selects concrete dependency versions. The minimum dependency matrix uses TextFSM 0.5.1 and JSON 2. A separate JSON 3 matrix uses the same published TextFSM package without modifying its dependency metadata.
169
169
 
170
170
  CLI entry points share layered configuration and `.env` loading; dotenv is a declared runtime dependency. Core library calls do not discover host files. Follow the [loading and migration reference](architecture.md#加载入口与厂商策略) (Chinese) for custom profiles, strategies, and protected hooks.
data/docs/usage.zh-CN.md CHANGED
@@ -2,11 +2,11 @@
2
2
 
3
3
  [English](usage.md) | [返回首页](../README.zh-CN.md) | [Netdisco 批量备份](netdisco.zh-CN.md)
4
4
 
5
- 支持 Ruby 3.4 及以上版本和 POSIX 系统。SSH 调用本机 OpenSSH,Telnet 需要本机安装 `telnet` 并显式选择。要求 [`expect-pty`](https://rubygems.org/gems/expect-pty) 0.9.4 及以上;[`textfsm`](https://rubygems.org/gems/textfsm) 由宿主选择版本,最低依赖测试覆盖 0.2.0。
5
+ 支持 Ruby 3.4 及以上版本和 POSIX 系统。SSH 调用本机 OpenSSH,Telnet 需要本机安装 `telnet` 并显式选择。要求 [`expect-pty`](https://rubygems.org/gems/expect-pty) 0.9.6 及以上、ctx_cli 0.4.x 和 [`textfsm`](https://rubygems.org/gems/textfsm) 0.5.1 及以上;具体版本由宿主锁定。
6
6
 
7
7
  脱敏直接复用 expect-pty 的公开 `Expect::Redactor` 接口;连接器只管理秘密作用域和配置输出的隐私策略。
8
8
 
9
- gemspec 声明 expect-pty 的接口版本下界;宿主应用通过自己的 Gemfile 和锁文件固定具体依赖版本。最低依赖组合使用 textfsm 0.2.0 与 JSON 2;JSON 3 另有固定 TextFSM 源码及显式依赖声明补丁的验证通道。开发工具及测试矩阵的版本约束不进入 gem 的运行依赖。
9
+ gemspec 声明所需接口的版本下界;宿主应用通过自己的 Gemfile 和锁文件固定具体依赖版本。最低依赖组合使用 textfsm 0.5.1 与 JSON 2;JSON 3 矩阵也使用同一已发布 TextFSM 包,无需源码或 metadata 补丁。开发工具及测试矩阵的版本约束不进入 gem 的运行依赖。
10
10
 
11
11
  CLI 与示例入口共用分层配置和 `.env` 加载,dotenv 已声明为运行时依赖;核心库调用不自动发现宿主文件。
12
12
 
@@ -27,7 +27,7 @@ module Net
27
27
  when "partial" then "Partially complete (#{code})"
28
28
  else "Incomplete (#{code})"
29
29
  end
30
- super(host: result.fetch("device").fetch("host"), success: status == "complete",
30
+ super(host: result.fetch("target").fetch("host"), success: status == "complete",
31
31
  duration_ms: result.fetch("duration_ms"), message: message, error_code: code&.to_sym)
32
32
  end
33
33
 
@@ -64,7 +64,7 @@ module Net
64
64
  def inspect_interface(interface, peers)
65
65
  peer = peers.first
66
66
  current = @descriptions[interface]
67
- row = { interface: peer.local_interface, neighbor: peer.neighbor_name, port: peer.neighbor_interface,
67
+ row = { interface: peer.local_interface, neighbor: peer.remote_name, port: peer.remote_interface,
68
68
  current: current, expected: nil, status: :unverified }
69
69
  @comparisons << row
70
70
  if peers.size != 1
@@ -78,7 +78,7 @@ module Net
78
78
  local = @strategy.configuration_interface(peer.local_interface)
79
79
  Description.validate_interface!(local)
80
80
  row.merge!(expected: proposed, status: compare_status(current, proposed, peer))
81
- @evidence[interface] = [peer.neighbor_name, peer.neighbor_interface, current]
81
+ @evidence[interface] = [peer.remote_name, peer.remote_interface, current]
82
82
  return if row[:status] == :matches
83
83
 
84
84
  @changes << Change.new(interface: local, old_description: current, new_description: proposed, neighbor: peer)
@@ -10,11 +10,11 @@ module Net
10
10
  # 将邻居名称和接口拼成默认描述;统一邻居接口简称,原始发现记录保持不变。
11
11
  def self.format(neighbor, abbreviate: true, lowercase: false)
12
12
  port = if abbreviate
13
- Name.short(neighbor.neighbor_interface, lowercase: lowercase)
13
+ Name.short(neighbor.remote_interface, lowercase: lowercase)
14
14
  else
15
- lowercase ? neighbor.neighbor_interface.downcase : neighbor.neighbor_interface
15
+ lowercase ? neighbor.remote_interface.downcase : neighbor.remote_interface
16
16
  end
17
- validate!("To_#{neighbor.neighbor_name.tr(" ", "_")}_#{port.tr(" ", "_")}")
17
+ validate!("To_#{neighbor.remote_name.tr(" ", "_")}_#{port.tr(" ", "_")}")
18
18
  end
19
19
 
20
20
  # 保留语义相同的旧描述;只归一末尾已知接口别名和大小写,不模糊匹配名称或端口编号。
@@ -4,11 +4,11 @@ module Net
4
4
  module Connector
5
5
  class Interfaces
6
6
  # 邻居身份拥有独立字符串,格式化回调不能改写发现证据。
7
- Neighbor = Data.define(:local_interface, :neighbor_name, :neighbor_interface, :chassis_id, :protocol) do
7
+ Neighbor = Data.define(:local_interface, :remote_name, :remote_interface, :remote_chassis_id, :protocol) do
8
8
  # 复制并冻结本地端口、邻居名称、远端端口及发现协议。
9
- def initialize(local_interface:, neighbor_name:, neighbor_interface:, chassis_id:, protocol:)
10
- fields = { local_interface: local_interface, neighbor_name: neighbor_name,
11
- neighbor_interface: neighbor_interface, chassis_id: chassis_id }
9
+ def initialize(local_interface:, remote_name:, remote_interface:, remote_chassis_id:, protocol:)
10
+ fields = { local_interface: local_interface, remote_name: remote_name,
11
+ remote_interface: remote_interface, remote_chassis_id: remote_chassis_id }
12
12
  raise ArgumentError, "neighbor fields must be Strings" unless fields.values.all?(String)
13
13
  raise ArgumentError, "neighbor protocol must be a Symbol" unless protocol.is_a?(Symbol)
14
14
 
@@ -18,8 +18,8 @@ module Net
18
18
  # 原始发现数据保留占位符;规划与下发重验共用身份校验,不能把未知名称写入描述。
19
19
  # MAC 是合法的 LLDP Port ID,不凭地址形状猜测设备角色,也不拿 chassis ID 补造名称。
20
20
  def identity_issue
21
- return :unknown_neighbor_name if unknown_identity?(neighbor_name)
22
- return :unknown_neighbor_interface if unknown_identity?(neighbor_interface)
21
+ return :unknown_neighbor_name if unknown_identity?(remote_name)
22
+ return :unknown_neighbor_interface if unknown_identity?(remote_interface)
23
23
 
24
24
  nil
25
25
  end
@@ -88,9 +88,9 @@ module Net
88
88
 
89
89
  rows.map do |row|
90
90
  Neighbor.new(local_interface: row.fetch("LOCAL_INTERFACE").strip.freeze,
91
- neighbor_name: row.fetch("NEIGHBOR_NAME", "").strip.freeze,
92
- neighbor_interface: row.fetch("NEIGHBOR_INTERFACE").strip.freeze,
93
- chassis_id: row.fetch("CHASSIS_ID", "").strip.freeze,
91
+ remote_name: row.fetch("NEIGHBOR_NAME", "").strip.freeze,
92
+ remote_interface: row.fetch("NEIGHBOR_INTERFACE").strip.freeze,
93
+ remote_chassis_id: row.fetch("CHASSIS_ID", "").strip.freeze,
94
94
  protocol: @strategy.protocol).freeze
95
95
  end
96
96
  end
@@ -272,7 +272,7 @@ module Net
272
272
  plan.changes.each do |change|
273
273
  Description.validate!(change.new_description)
274
274
  unless evidence.fetch(@strategy.interface_key(change.interface)) ==
275
- [change.neighbor.neighbor_name, change.neighbor.neighbor_interface, change.old_description]
275
+ [change.neighbor.remote_name, change.neighbor.remote_interface, change.old_description]
276
276
  raise ArgumentError, "plan changes do not match its discovery evidence"
277
277
  end
278
278
  end
@@ -319,7 +319,7 @@ module Net
319
319
 
320
320
  interfaces.transform_values do |peers|
321
321
  peer = peers.fetch(0)
322
- [peer.neighbor_name, peer.neighbor_interface, current.fetch(@strategy.interface_key(peer.local_interface))].freeze
322
+ [peer.remote_name, peer.remote_interface, current.fetch(@strategy.interface_key(peer.local_interface))].freeze
323
323
  end.freeze
324
324
  end
325
325
 
@@ -130,6 +130,21 @@ def read_file(parent, name, missing=False, consume=None):
130
130
  digest.update(chunk)
131
131
  if consume is not None and consume(chunk) != len(chunk):
132
132
  raise IOError("incomplete file write")
133
+ # 同一时钟粒度内的覆写可能不改变 stat 时间;投递后重读摘要核对已发送字节。
134
+ if consume is not None:
135
+ f.seek(0)
136
+ verified = hashlib.sha256()
137
+ verified_size = 0
138
+ while True:
139
+ chunk = f.read(CHUNK_BYTES)
140
+ if not chunk:
141
+ break
142
+ verified_size += len(chunk)
143
+ if verified_size > MAX_BYTES:
144
+ raise ValueError("oversized file")
145
+ verified.update(chunk)
146
+ if verified_size != size or verified.digest() != digest.digest():
147
+ raise ValueError("file changed while delivering")
133
148
  after = os.fstat(f.fileno())
134
149
  if size != after.st_size or fingerprint(before) != fingerprint(after):
135
150
  raise ValueError("file changed while reading")
@@ -51,10 +51,10 @@ module Net
51
51
 
52
52
  # 使用当前模板和端口展示策略生成缺失或确需修正的目标描述。
53
53
  def description_for(neighbor)
54
- port = neighbor.neighbor_interface
54
+ port = neighbor.remote_interface
55
55
  port = Net::Connector::Interfaces::Name.short(port) if abbreviate_ports
56
56
  port = port.downcase if lowercase_ports
57
- format(neighbor: neighbor.neighbor_name, port: port)
57
+ format(neighbor: neighbor.remote_name, port: port)
58
58
  end
59
59
 
60
60
  # 仅显式声明的旧名称前缀可保留;不把未知名称、包含匹配或不同编号当作同一邻居。
@@ -63,7 +63,7 @@ module Net
63
63
  return true if comparison.equivalent?(current, expected)
64
64
 
65
65
  neighbor_name_prefixes.any? do |prefix|
66
- variant = neighbor.with(neighbor_name: prefix + neighbor.neighbor_name)
66
+ variant = neighbor.with(remote_name: prefix + neighbor.remote_name)
67
67
  comparison.equivalent?(current, description_for(variant))
68
68
  end
69
69
  end
@@ -3,6 +3,6 @@
3
3
  module Net
4
4
  module Connector
5
5
  # gemspec、CLI 与发布工具共用此版本,运行时读取不触发设备依赖加载。
6
- VERSION = "0.19.0"
6
+ VERSION = "0.21.0"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-connector
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.21.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - net-connector contributors
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-10-29 00:00:00.000000000 Z
10
+ date: 2026-10-30 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: ctx_cli
@@ -15,42 +15,54 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: '0'
18
+ version: 0.5.0
19
+ - - "<"
20
+ - !ruby/object:Gem::Version
21
+ version: '0.6'
19
22
  type: :runtime
20
23
  prerelease: false
21
24
  version_requirements: !ruby/object:Gem::Requirement
22
25
  requirements:
23
26
  - - ">="
24
27
  - !ruby/object:Gem::Version
25
- version: '0'
28
+ version: 0.5.0
29
+ - - "<"
30
+ - !ruby/object:Gem::Version
31
+ version: '0.6'
26
32
  - !ruby/object:Gem::Dependency
27
33
  name: expect-pty
28
34
  requirement: !ruby/object:Gem::Requirement
29
35
  requirements:
30
36
  - - ">="
31
37
  - !ruby/object:Gem::Version
32
- version: '0'
38
+ version: 0.9.6
39
+ - - "<"
40
+ - !ruby/object:Gem::Version
41
+ version: '0.10'
33
42
  type: :runtime
34
43
  prerelease: false
35
44
  version_requirements: !ruby/object:Gem::Requirement
36
45
  requirements:
37
46
  - - ">="
38
47
  - !ruby/object:Gem::Version
39
- version: '0'
48
+ version: 0.9.6
49
+ - - "<"
50
+ - !ruby/object:Gem::Version
51
+ version: '0.10'
40
52
  - !ruby/object:Gem::Dependency
41
53
  name: textfsm
42
54
  requirement: !ruby/object:Gem::Requirement
43
55
  requirements:
44
56
  - - ">="
45
57
  - !ruby/object:Gem::Version
46
- version: '0'
58
+ version: 0.5.1
47
59
  type: :runtime
48
60
  prerelease: false
49
61
  version_requirements: !ruby/object:Gem::Requirement
50
62
  requirements:
51
63
  - - ">="
52
64
  - !ruby/object:Gem::Version
53
- version: '0'
65
+ version: 0.5.1
54
66
  - !ruby/object:Gem::Dependency
55
67
  name: pg
56
68
  requirement: !ruby/object:Gem::Requirement