foil-server 0.4.0 → 0.5.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 +4 -4
- data/README.md +3 -1
- data/lib/foil/server/client.rb +25 -4
- data/lib/foil/server/sealed_token.rb +18 -1
- data/lib/foil/server/version.rb +1 -1
- data/spec/fixtures/api/fingerprints/detail.json +1 -1
- data/spec/fixtures/api/fingerprints/list.json +1 -1
- data/spec/fixtures/api/sessions/detail.json +10 -7
- data/spec/fixtures/api/sessions/list.json +1 -0
- data/spec/openapi.json +806 -324
- 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: e998be2281e9d8fbacd45e49596b2424d46509066ff8f97e1ddfa5763531ba10
|
|
4
|
+
data.tar.gz: be9cae7a65e5d4e13c0ef726d56f1ca9281237b50e79345a0dc5a5904987d9f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f9bfc32b352566af63551b720bba2f6dc790040073cb793ffa3c31017d126d960ae2cdacc0a1e4cb6db89785a4eb074456e34945274578d01744ba849eefc76b
|
|
7
|
+
data.tar.gz: 21141586684db218908995affc1fd2ac5271dca1ae273a2208682c77a1936b4427c08d376d45c337f73e1d1ec712f906770b660a3b7f049beb30873d36647f25
|
data/README.md
CHANGED
|
@@ -38,10 +38,12 @@ require "foil/server"
|
|
|
38
38
|
|
|
39
39
|
client = Foil::Server::Client.new(secret_key: "sk_live_...")
|
|
40
40
|
|
|
41
|
-
page = client.sessions.list(verdict: "bot", limit: 25)
|
|
41
|
+
page = client.sessions.list(verdict: "bot", limit: 25, client_user_id: "user_123", client_application_id: "app_123")
|
|
42
42
|
session = client.sessions.get("sid_0123456789abcdefghjkmnpqrs")
|
|
43
43
|
client.sessions.attach_client_user("sid_0123456789abcdefghjkmnpqrs", "user_123")
|
|
44
44
|
client.sessions.clear_client_user("sid_0123456789abcdefghjkmnpqrs")
|
|
45
|
+
client.sessions.attach_client_application("sid_0123456789abcdefghjkmnpqrs", "app_123")
|
|
46
|
+
client.sessions.clear_client_application("sid_0123456789abcdefghjkmnpqrs")
|
|
45
47
|
|
|
46
48
|
puts "#{session[:decision][:automation_status]} #{session[:highlights].first&.fetch(:summary, nil)}"
|
|
47
49
|
```
|
data/lib/foil/server/client.rb
CHANGED
|
@@ -151,12 +151,14 @@ module Foil
|
|
|
151
151
|
end
|
|
152
152
|
|
|
153
153
|
class SessionsResource < BaseResource
|
|
154
|
-
def list(limit: nil, cursor: nil, verdict: nil, search: nil)
|
|
154
|
+
def list(limit: nil, cursor: nil, verdict: nil, search: nil, client_user_id: nil, client_application_id: nil)
|
|
155
155
|
payload = @client.request_json("GET", "/v1/sessions", query: {
|
|
156
156
|
limit: limit,
|
|
157
157
|
cursor: cursor,
|
|
158
158
|
verdict: verdict,
|
|
159
|
-
search: search
|
|
159
|
+
search: search,
|
|
160
|
+
client_user_id: client_user_id,
|
|
161
|
+
client_application_id: client_application_id
|
|
160
162
|
})
|
|
161
163
|
list_result(payload)
|
|
162
164
|
end
|
|
@@ -177,11 +179,30 @@ module Foil
|
|
|
177
179
|
})[:data]
|
|
178
180
|
end
|
|
179
181
|
|
|
180
|
-
def
|
|
182
|
+
def attach_client_application(session_id, client_application_id)
|
|
183
|
+
@client.request_json("PATCH", "/v1/sessions/#{CGI.escape(session_id)}", body: {
|
|
184
|
+
client_application_id: client_application_id
|
|
185
|
+
})[:data]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def clear_client_application(session_id)
|
|
189
|
+
@client.request_json("PATCH", "/v1/sessions/#{CGI.escape(session_id)}", body: {
|
|
190
|
+
client_application_id: nil
|
|
191
|
+
})[:data]
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def iter(limit: nil, verdict: nil, search: nil, client_user_id: nil, client_application_id: nil)
|
|
181
195
|
Enumerator.new do |yielder|
|
|
182
196
|
cursor = nil
|
|
183
197
|
loop do
|
|
184
|
-
page = list(
|
|
198
|
+
page = list(
|
|
199
|
+
limit: limit,
|
|
200
|
+
cursor: cursor,
|
|
201
|
+
verdict: verdict,
|
|
202
|
+
search: search,
|
|
203
|
+
client_user_id: client_user_id,
|
|
204
|
+
client_application_id: client_application_id
|
|
205
|
+
)
|
|
185
206
|
page.items.each { |item| yielder << item }
|
|
186
207
|
break unless page.has_more && page.next_cursor
|
|
187
208
|
|
|
@@ -18,6 +18,8 @@ module Foil
|
|
|
18
18
|
V2_RECIPIENT_BYTES = RECIPIENT_ID_BYTES + NONCE_BYTES + CONTENT_KEY_BYTES + TAG_BYTES
|
|
19
19
|
V2_PAYLOAD_AAD_PREFIX = "foil-sealed-results-v2\0payload\0".b
|
|
20
20
|
V2_WRAP_AAD_PREFIX = "foil-sealed-results-v2\0recipient\0".b
|
|
21
|
+
# Decompressed payloads are a few kilobytes; the cap bounds memory if a token decompresses to far more.
|
|
22
|
+
MAX_PAYLOAD_BYTES = 1024 * 1024
|
|
21
23
|
|
|
22
24
|
module_function
|
|
23
25
|
|
|
@@ -30,7 +32,7 @@ module Foil
|
|
|
30
32
|
raise TokenVerificationError, "Foil token is too short." if raw.bytesize < 29
|
|
31
33
|
|
|
32
34
|
compressed = decrypt_payload(raw, resolved_secret)
|
|
33
|
-
payload = JSON.parse(
|
|
35
|
+
payload = JSON.parse(inflate_payload(compressed))
|
|
34
36
|
deep_symbolize(payload)
|
|
35
37
|
rescue ConfigurationError, TokenVerificationError
|
|
36
38
|
raise
|
|
@@ -49,6 +51,21 @@ module Foil
|
|
|
49
51
|
end
|
|
50
52
|
private_class_method :derive_key
|
|
51
53
|
|
|
54
|
+
def inflate_payload(compressed)
|
|
55
|
+
inflater = Zlib::Inflate.new
|
|
56
|
+
payload = "".b
|
|
57
|
+
inflater.inflate(compressed) do |chunk|
|
|
58
|
+
payload << chunk
|
|
59
|
+
raise TokenVerificationError, "Foil token payload is too large." if payload.bytesize > MAX_PAYLOAD_BYTES
|
|
60
|
+
end
|
|
61
|
+
raise Zlib::BufError, "Foil token payload is truncated." unless inflater.finished?
|
|
62
|
+
|
|
63
|
+
payload
|
|
64
|
+
ensure
|
|
65
|
+
inflater&.close
|
|
66
|
+
end
|
|
67
|
+
private_class_method :inflate_payload
|
|
68
|
+
|
|
52
69
|
def decrypt_gcm(ciphertext, key, nonce, tag, aad = "".b)
|
|
53
70
|
cipher = OpenSSL::Cipher.new("aes-256-gcm")
|
|
54
71
|
cipher.decrypt
|
data/lib/foil/server/version.rb
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
"id": "sid_0123456789abcdefghjkmnpqrs",
|
|
5
5
|
"created_at": "2026-03-24T20:00:00.000Z",
|
|
6
6
|
"client_user_id": "user_123",
|
|
7
|
+
"client_application_id": "app_123",
|
|
7
8
|
"behavior": null,
|
|
8
9
|
"decision": {
|
|
9
10
|
"event_id": "evt_23456789abcdefghjkmnpqrstv",
|
|
@@ -144,7 +145,7 @@
|
|
|
144
145
|
"accuracy_radius_km": 10
|
|
145
146
|
},
|
|
146
147
|
"routing": {
|
|
147
|
-
"asn": "
|
|
148
|
+
"asn": "AS64512",
|
|
148
149
|
"organization": "Example Networks"
|
|
149
150
|
},
|
|
150
151
|
"anonymity": {
|
|
@@ -174,7 +175,7 @@
|
|
|
174
175
|
"client_types": [
|
|
175
176
|
"consumer"
|
|
176
177
|
],
|
|
177
|
-
"client_count":
|
|
178
|
+
"client_count": null
|
|
178
179
|
},
|
|
179
180
|
"evaluated_at": "2026-03-24T20:00:05.000Z"
|
|
180
181
|
},
|
|
@@ -206,7 +207,8 @@
|
|
|
206
207
|
"lifecycle": {
|
|
207
208
|
"first_seen_at": "2026-03-01T18:22:11.000Z",
|
|
208
209
|
"last_seen_at": "2026-03-24T20:00:05.000Z",
|
|
209
|
-
"seen_count": 14
|
|
210
|
+
"seen_count": 14,
|
|
211
|
+
"resolution_count": 14
|
|
210
212
|
}
|
|
211
213
|
},
|
|
212
214
|
"connection_fingerprint": {
|
|
@@ -383,7 +385,7 @@
|
|
|
383
385
|
},
|
|
384
386
|
"canvas": {
|
|
385
387
|
"hash": 123456,
|
|
386
|
-
"geometry_hash":
|
|
388
|
+
"geometry_hash": null,
|
|
387
389
|
"text_hash": 112233,
|
|
388
390
|
"winding": null,
|
|
389
391
|
"noise_detected": true,
|
|
@@ -398,6 +400,7 @@
|
|
|
398
400
|
"parameters_hash": "params_123",
|
|
399
401
|
"extensions_hash": 333444,
|
|
400
402
|
"extension_parameters_hash": "webgl2_456",
|
|
403
|
+
"webgl2_parameters_hash": "webgl2_456",
|
|
401
404
|
"shader_precision_hash": 777888
|
|
402
405
|
},
|
|
403
406
|
"webgpu": {
|
|
@@ -412,7 +415,7 @@
|
|
|
412
415
|
"audio": {
|
|
413
416
|
"hash": 124.0434,
|
|
414
417
|
"sample_rate": 48000,
|
|
415
|
-
"channel_count":
|
|
418
|
+
"channel_count": 2,
|
|
416
419
|
"voice_count": 3,
|
|
417
420
|
"local_voice_count": 2,
|
|
418
421
|
"default_voice_lang": "en-US",
|
|
@@ -420,11 +423,11 @@
|
|
|
420
423
|
},
|
|
421
424
|
"fonts": {
|
|
422
425
|
"detected_count": 2,
|
|
423
|
-
"tested_count":
|
|
426
|
+
"tested_count": 41,
|
|
424
427
|
"enumeration_hash": 3649417752,
|
|
425
428
|
"metrics_hash": 223344,
|
|
426
429
|
"preferences_hash": null,
|
|
427
|
-
"emoji_hash":
|
|
430
|
+
"emoji_hash": "5f0e2a71"
|
|
428
431
|
},
|
|
429
432
|
"media": {
|
|
430
433
|
"device_count": 1,
|