mlld 2.0.3 → 2.0.5
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 +1 -0
- data/lib/mlld.rb +59 -6
- 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: ff041879477a16d48049a2d8e1d220960c88622f6d544db8b00af88ec4952707
|
|
4
|
+
data.tar.gz: a5b86461dc631d729c50e58822374bc0e08669ae98c4f96665febd9aa01ef449
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 819fbc89a98bdccffc5a012ece626f339caeb27b1143364dfcfe60e87670f320e2e7f1afc28aa1795584fab78a7f8bf73b4788490dfa845cf11c8ab34f7ea614
|
|
7
|
+
data.tar.gz: 79c752b1c2e328cb0f7f31330751764119a6bff7d5b4ec7839d06d57d6be024a7a84cfb84c6440d16a0a530a29a2389a498e8493211d1ae0b48d64568bed7fd8
|
data/README.md
CHANGED
|
@@ -94,3 +94,4 @@ puts handle.result
|
|
|
94
94
|
|
|
95
95
|
- Each `Client` keeps one live RPC subprocess for repeated calls.
|
|
96
96
|
- `ExecuteResult.state_writes` merges final-result writes and streamed `state:write` events.
|
|
97
|
+
- `ExecuteResult.denials` collects structured guard/policy label-flow denials observed during execution.
|
data/lib/mlld.rb
CHANGED
|
@@ -19,7 +19,8 @@ module Mlld
|
|
|
19
19
|
StateWrite = Struct.new(:path, :value, :timestamp, keyword_init: true)
|
|
20
20
|
Metrics = Struct.new(:total_ms, :parse_ms, :evaluate_ms, keyword_init: true)
|
|
21
21
|
Effect = Struct.new(:type, :content, :security, keyword_init: true)
|
|
22
|
-
|
|
22
|
+
GuardDenial = Struct.new(:guard, :operation, :reason, :rule, :labels, :args, keyword_init: true)
|
|
23
|
+
ExecuteResult = Struct.new(:output, :state_writes, :exports, :effects, :denials, :metrics, keyword_init: true)
|
|
23
24
|
|
|
24
25
|
Executable = Struct.new(:name, :params, :labels, keyword_init: true)
|
|
25
26
|
Import = Struct.new(:from, :names, keyword_init: true)
|
|
@@ -57,8 +58,8 @@ module Mlld
|
|
|
57
58
|
@client.send_cancel(@request_id)
|
|
58
59
|
end
|
|
59
60
|
|
|
60
|
-
def update_state(path, value, timeout: nil)
|
|
61
|
-
@client.send_state_update(@request_id, path, value, timeout || @timeout)
|
|
61
|
+
def update_state(path, value, labels: nil, timeout: nil)
|
|
62
|
+
@client.send_state_update(@request_id, path, value, timeout || @timeout, labels: labels)
|
|
62
63
|
end
|
|
63
64
|
|
|
64
65
|
protected
|
|
@@ -200,6 +201,7 @@ module Mlld
|
|
|
200
201
|
script,
|
|
201
202
|
file_path: nil,
|
|
202
203
|
payload: nil,
|
|
204
|
+
payload_labels: nil,
|
|
203
205
|
state: nil,
|
|
204
206
|
dynamic_modules: nil,
|
|
205
207
|
dynamic_module_source: nil,
|
|
@@ -211,6 +213,7 @@ module Mlld
|
|
|
211
213
|
script,
|
|
212
214
|
file_path: file_path,
|
|
213
215
|
payload: payload,
|
|
216
|
+
payload_labels: payload_labels,
|
|
214
217
|
state: state,
|
|
215
218
|
dynamic_modules: dynamic_modules,
|
|
216
219
|
dynamic_module_source: dynamic_module_source,
|
|
@@ -224,6 +227,7 @@ module Mlld
|
|
|
224
227
|
script,
|
|
225
228
|
file_path: nil,
|
|
226
229
|
payload: nil,
|
|
230
|
+
payload_labels: nil,
|
|
227
231
|
state: nil,
|
|
228
232
|
dynamic_modules: nil,
|
|
229
233
|
dynamic_module_source: nil,
|
|
@@ -234,6 +238,8 @@ module Mlld
|
|
|
234
238
|
params = { 'script' => script }
|
|
235
239
|
params['filePath'] = file_path if file_path
|
|
236
240
|
params['payload'] = payload unless payload.nil?
|
|
241
|
+
normalized_payload_labels = normalize_payload_labels(payload_labels)
|
|
242
|
+
params['payloadLabels'] = normalized_payload_labels if normalized_payload_labels
|
|
237
243
|
params['state'] = state if state
|
|
238
244
|
params['dynamicModules'] = dynamic_modules if dynamic_modules
|
|
239
245
|
params['dynamicModuleSource'] = dynamic_module_source if dynamic_module_source
|
|
@@ -252,6 +258,7 @@ module Mlld
|
|
|
252
258
|
def execute(
|
|
253
259
|
filepath,
|
|
254
260
|
payload = nil,
|
|
261
|
+
payload_labels: nil,
|
|
255
262
|
state: nil,
|
|
256
263
|
dynamic_modules: nil,
|
|
257
264
|
dynamic_module_source: nil,
|
|
@@ -262,6 +269,7 @@ module Mlld
|
|
|
262
269
|
execute_async(
|
|
263
270
|
filepath,
|
|
264
271
|
payload,
|
|
272
|
+
payload_labels: payload_labels,
|
|
265
273
|
state: state,
|
|
266
274
|
dynamic_modules: dynamic_modules,
|
|
267
275
|
dynamic_module_source: dynamic_module_source,
|
|
@@ -274,6 +282,7 @@ module Mlld
|
|
|
274
282
|
def execute_async(
|
|
275
283
|
filepath,
|
|
276
284
|
payload = nil,
|
|
285
|
+
payload_labels: nil,
|
|
277
286
|
state: nil,
|
|
278
287
|
dynamic_modules: nil,
|
|
279
288
|
dynamic_module_source: nil,
|
|
@@ -283,6 +292,8 @@ module Mlld
|
|
|
283
292
|
)
|
|
284
293
|
params = { 'filepath' => filepath }
|
|
285
294
|
params['payload'] = payload unless payload.nil?
|
|
295
|
+
normalized_payload_labels = normalize_payload_labels(payload_labels)
|
|
296
|
+
params['payloadLabels'] = normalized_payload_labels if normalized_payload_labels
|
|
286
297
|
params['state'] = state if state
|
|
287
298
|
params['dynamicModules'] = dynamic_modules if dynamic_modules
|
|
288
299
|
params['dynamicModuleSource'] = dynamic_module_source if dynamic_module_source
|
|
@@ -309,7 +320,7 @@ module Mlld
|
|
|
309
320
|
nil
|
|
310
321
|
end
|
|
311
322
|
|
|
312
|
-
def send_state_update(request_id, path, value, timeout)
|
|
323
|
+
def send_state_update(request_id, path, value, timeout, labels: nil)
|
|
313
324
|
unless path.is_a?(String) && !path.strip.empty?
|
|
314
325
|
raise Error.new('state update path is required', code: 'INVALID_REQUEST')
|
|
315
326
|
end
|
|
@@ -317,14 +328,17 @@ module Mlld
|
|
|
317
328
|
resolved_timeout = resolve_timeout(timeout)
|
|
318
329
|
max_wait = resolved_timeout || 2.0
|
|
319
330
|
deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + max_wait
|
|
331
|
+
normalized_labels = normalize_label_list(labels)
|
|
320
332
|
|
|
321
333
|
loop do
|
|
322
334
|
begin
|
|
323
|
-
|
|
335
|
+
params = {
|
|
324
336
|
'requestId' => request_id,
|
|
325
337
|
'path' => path,
|
|
326
338
|
'value' => value
|
|
327
|
-
}
|
|
339
|
+
}
|
|
340
|
+
params['labels'] = normalized_labels if normalized_labels
|
|
341
|
+
request('state:update', params, resolved_timeout)
|
|
328
342
|
return nil
|
|
329
343
|
rescue Error => error
|
|
330
344
|
raise unless error.code == 'REQUEST_NOT_FOUND'
|
|
@@ -335,6 +349,31 @@ module Mlld
|
|
|
335
349
|
end
|
|
336
350
|
end
|
|
337
351
|
|
|
352
|
+
def normalize_payload_labels(payload_labels)
|
|
353
|
+
return nil if payload_labels.nil?
|
|
354
|
+
return nil unless payload_labels.is_a?(Hash)
|
|
355
|
+
|
|
356
|
+
normalized = {}
|
|
357
|
+
payload_labels.each do |key, labels|
|
|
358
|
+
deduped = normalize_label_list(labels)
|
|
359
|
+
normalized[key] = deduped if deduped
|
|
360
|
+
end
|
|
361
|
+
normalized.empty? ? nil : normalized
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
def normalize_label_list(labels)
|
|
365
|
+
return nil if labels.nil?
|
|
366
|
+
|
|
367
|
+
raw = labels.is_a?(Array) ? labels : [labels]
|
|
368
|
+
normalized = raw
|
|
369
|
+
.select { |label| label.is_a?(String) }
|
|
370
|
+
.map(&:strip)
|
|
371
|
+
.reject(&:empty?)
|
|
372
|
+
.uniq
|
|
373
|
+
|
|
374
|
+
normalized.empty? ? nil : normalized
|
|
375
|
+
end
|
|
376
|
+
|
|
338
377
|
def await_request(request_id, response_queue, timeout)
|
|
339
378
|
state_write_events = []
|
|
340
379
|
deadline = timeout ? Process.clock_gettime(Process::CLOCK_MONOTONIC) + timeout : nil
|
|
@@ -412,11 +451,25 @@ module Mlld
|
|
|
412
451
|
)
|
|
413
452
|
end.compact
|
|
414
453
|
|
|
454
|
+
denials = Array(result['denials']).map do |entry|
|
|
455
|
+
next unless entry.is_a?(Hash)
|
|
456
|
+
|
|
457
|
+
GuardDenial.new(
|
|
458
|
+
guard: entry['guard'],
|
|
459
|
+
operation: entry['operation'].to_s,
|
|
460
|
+
reason: entry['reason'].to_s,
|
|
461
|
+
rule: entry['rule'],
|
|
462
|
+
labels: Array(entry['labels']).select { |label| label.is_a?(String) },
|
|
463
|
+
args: entry['args'].is_a?(Hash) ? entry['args'] : nil
|
|
464
|
+
)
|
|
465
|
+
end.compact
|
|
466
|
+
|
|
415
467
|
ExecuteResult.new(
|
|
416
468
|
output: result['output'].to_s,
|
|
417
469
|
state_writes: state_writes,
|
|
418
470
|
exports: result.fetch('exports', []),
|
|
419
471
|
effects: effects,
|
|
472
|
+
denials: denials,
|
|
420
473
|
metrics: metrics
|
|
421
474
|
)
|
|
422
475
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mlld
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0.
|
|
4
|
+
version: 2.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- mlld-lang
|
|
@@ -39,7 +39,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '0'
|
|
41
41
|
requirements: []
|
|
42
|
-
rubygems_version: 4.0.
|
|
42
|
+
rubygems_version: 4.0.6
|
|
43
43
|
specification_version: 4
|
|
44
44
|
summary: Ruby wrapper for the mlld CLI
|
|
45
45
|
test_files: []
|