secryst 1.0.0 → 1.0.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/lib/secryst/imf.rb +24 -2
- data/lib/secryst/version.rb +1 -1
- data/spec/secryst/imf_spec.rb +64 -0
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 41fa8b9cc35c52b6ed2a5ffb898d40f83df55e89533d48878e899bcf20ee142f
|
|
4
|
+
data.tar.gz: 697eae0009ab525080e429e213b09b4b06a828a4157db9649a6cea04abd16dd7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 007d2fb6944c93ee1e38ace06e06a025336b00318c7a5446e9daf33cc8ab0448caa4646dd943176452d1d4fe61ea3d706e3713b0deabc9f526b24e600707f432
|
|
7
|
+
data.tar.gz: 8dfdc84550803d2d87566fc1c70c268505b05fe963213e98e12a89a16cada7e07eedfcb8cc138738b615b346db554b13fa71a1a352ab721581b359d3d588faca
|
data/lib/secryst/imf.rb
CHANGED
|
@@ -15,7 +15,7 @@ module Secryst
|
|
|
15
15
|
EOS_ID = 1
|
|
16
16
|
UNK_ID = 2
|
|
17
17
|
|
|
18
|
-
DEFAULT_INDEX_URL = "https://
|
|
18
|
+
DEFAULT_INDEX_URL = "https://github.com/interscript/interscript-ml/releases/download/index-v1/models-index.yaml"
|
|
19
19
|
|
|
20
20
|
class FormatError < StandardError; end
|
|
21
21
|
class RegistryError < StandardError; end
|
|
@@ -142,7 +142,7 @@ module Secryst
|
|
|
142
142
|
|
|
143
143
|
def load_index(source)
|
|
144
144
|
text = if source.start_with?("http://", "https://")
|
|
145
|
-
|
|
145
|
+
fetch_index_with_sidecar(source)
|
|
146
146
|
else
|
|
147
147
|
File.read(source)
|
|
148
148
|
end
|
|
@@ -150,6 +150,28 @@ module Secryst
|
|
|
150
150
|
raise RegistryError, "index must have version: 1" if raw["version"] != 1
|
|
151
151
|
raw.fetch("models", {})
|
|
152
152
|
end
|
|
153
|
+
public :load_index
|
|
154
|
+
|
|
155
|
+
# HTTP sources must ship a sibling .sha256 sidecar; verify the
|
|
156
|
+
# body against it before parsing (GitHub Releases index assets do).
|
|
157
|
+
def fetch_index_with_sidecar(source)
|
|
158
|
+
body = URI.open(source, "rb") { |remote| remote.read }
|
|
159
|
+
sidecar =
|
|
160
|
+
begin
|
|
161
|
+
URI.open("#{source}.sha256") { |remote| remote.read }
|
|
162
|
+
rescue OpenURI::HTTPError => e
|
|
163
|
+
raise RegistryError, "index sha256 sidecar missing: #{source}.sha256 (#{e.message})"
|
|
164
|
+
end
|
|
165
|
+
expected = sidecar.to_s.strip.split(/\s+/).first.to_s
|
|
166
|
+
unless expected.match?(/\A[0-9a-fA-F]{64}\z/)
|
|
167
|
+
raise RegistryError, "index sha256 sidecar malformed: #{source}.sha256"
|
|
168
|
+
end
|
|
169
|
+
actual = Digest::SHA256.hexdigest(body)
|
|
170
|
+
unless actual == expected.downcase
|
|
171
|
+
raise RegistryError, "index sha256 mismatch: got #{actual}, sidecar says #{expected.downcase}"
|
|
172
|
+
end
|
|
173
|
+
body.force_encoding(Encoding::UTF_8)
|
|
174
|
+
end
|
|
153
175
|
end
|
|
154
176
|
end
|
|
155
177
|
end
|
data/lib/secryst/version.rb
CHANGED
data/spec/secryst/imf_spec.rb
CHANGED
|
@@ -178,3 +178,67 @@ RSpec.describe Secryst::IMF do
|
|
|
178
178
|
end
|
|
179
179
|
end
|
|
180
180
|
end
|
|
181
|
+
|
|
182
|
+
describe "index distribution contract" do
|
|
183
|
+
it "pins DEFAULT_INDEX_URL to a GitHub Release asset, never raw" do
|
|
184
|
+
expect(Secryst::IMF::DEFAULT_INDEX_URL).to match(
|
|
185
|
+
%r{\Ahttps://github\.com/interscript/interscript-ml/releases/download/index-v\d+/models-index\.yaml\z}
|
|
186
|
+
)
|
|
187
|
+
expect(Secryst::IMF::DEFAULT_INDEX_URL).not_to include("raw.githubusercontent")
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it "verifies the .sha256 sidecar on HTTP index fetches" do
|
|
191
|
+
require "socket"
|
|
192
|
+
body = "version: 1\nmodels: {}\n"
|
|
193
|
+
good = Digest::SHA256.hexdigest(body)
|
|
194
|
+
bad = "0" * 64
|
|
195
|
+
|
|
196
|
+
serve = lambda do |sidecar, &blk|
|
|
197
|
+
server = TCPServer.new("127.0.0.1", 0)
|
|
198
|
+
port = server.addr[1]
|
|
199
|
+
thread = Thread.new do
|
|
200
|
+
loop do
|
|
201
|
+
client = server.accept rescue break
|
|
202
|
+
request = client.readline
|
|
203
|
+
client.each_line { |line| break if line == "\r\n" }
|
|
204
|
+
path = request.split(" ")[1]
|
|
205
|
+
case path
|
|
206
|
+
when "/models-index.yaml"
|
|
207
|
+
client.write("HTTP/1.1 200 OK\r\nContent-Length: #{body.bytesize}\r\n\r\n#{body}")
|
|
208
|
+
when "/models-index.yaml.sha256"
|
|
209
|
+
if sidecar.nil?
|
|
210
|
+
client.write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n")
|
|
211
|
+
else
|
|
212
|
+
payload = "#{sidecar} models-index.yaml\n"
|
|
213
|
+
client.write("HTTP/1.1 200 OK\r\nContent-Length: #{payload.bytesize}\r\n\r\n#{payload}")
|
|
214
|
+
end
|
|
215
|
+
else
|
|
216
|
+
client.write("HTTP/1.1 404 Not Found\r\nContent-Length: 0\r\n\r\n")
|
|
217
|
+
end
|
|
218
|
+
client.close
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
begin
|
|
222
|
+
blk.call("http://127.0.0.1:#{port}/models-index.yaml")
|
|
223
|
+
ensure
|
|
224
|
+
server.close
|
|
225
|
+
thread.join(5)
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
serve.call(good) do |url|
|
|
230
|
+
entries = Secryst::IMF.load_index(url)
|
|
231
|
+
expect(entries).to eq({})
|
|
232
|
+
end
|
|
233
|
+
serve.call(bad) do |url|
|
|
234
|
+
expect {
|
|
235
|
+
Secryst::IMF.load_index(url)
|
|
236
|
+
}.to raise_error(Secryst::IMF::RegistryError, /index sha256 mismatch/)
|
|
237
|
+
end
|
|
238
|
+
serve.call(nil) do |url|
|
|
239
|
+
expect {
|
|
240
|
+
Secryst::IMF.load_index(url)
|
|
241
|
+
}.to raise_error(Secryst::IMF::RegistryError, /index sha256/)
|
|
242
|
+
end
|
|
243
|
+
end
|
|
244
|
+
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: secryst
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Interscript / Secryst contributors
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: thor
|