visiq 0.1.0-x86_64-linux
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/LICENSE +21 -0
- data/README.md +49 -0
- data/lib/visiq.rb +113 -0
- data/vendor/libvisiq_core.so +0 -0
- metadata +69 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 002da0e84b12a9803aa799a69cf53d9d31f354b699ceba941ad81a561d0ed936
|
|
4
|
+
data.tar.gz: acc2f808fe222469b2248ff7755f57bf130bf4ae95444093116dfc700a13fecf
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: b496fbf49ca2f4eb7086e4363e02de85edc96a09af7f5e1cdd3fd6e69bb0534b4252bc30a4eb974a2f36b16903b00b654c15eaa77920aca2760ae2843056be86
|
|
7
|
+
data.tar.gz: 1f6d7560dabe0489a5a6a7f3c2c389a38406fbb22e82fc80559d64cf6e5e0f0c83f813f2b300423871cc9df1dee13ec43d8ecc9a81a7d7f49555525c2683df32
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 VisIQ Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# visiq — VisIQ agent-governance SDK for Ruby
|
|
2
|
+
|
|
3
|
+
Local, in-process governance decisions for AI agents. ONE compiled Rust core
|
|
4
|
+
(Path B) makes the **same** decisions as the shipped TypeScript SDK
|
|
5
|
+
(`@visiq/harness`), bound to Ruby through the stdlib `Fiddle` FFI. The engine
|
|
6
|
+
ships as **compiled machine code** (closed); the Ruby is thin FFI plumbing only.
|
|
7
|
+
|
|
8
|
+
- **Local & fast** — every decision is in-process, no network.
|
|
9
|
+
- **Fails closed (G001)** — malformed input, or a core that can't load, denies.
|
|
10
|
+
- **Cross-language parity** — reproduces the exact decisions of the TS/Python/…
|
|
11
|
+
SDKs from the same core, verified against a shared corpus.
|
|
12
|
+
|
|
13
|
+
## Install
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
gem install visiq
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Native, per-platform "fat" gems are published for macOS (arm64, x86_64) and Linux
|
|
20
|
+
(x86_64, aarch64) — `gem install` selects the one matching your platform and it
|
|
21
|
+
bundles the compiled core. **Ruby ≥ 3.0.**
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
```ruby
|
|
26
|
+
require "visiq"
|
|
27
|
+
|
|
28
|
+
bundle = load_rules_bundle # your VisIQ rules bundle (Hash)
|
|
29
|
+
|
|
30
|
+
# Gate a tool/action call — block unless allowed.
|
|
31
|
+
d = Visiq.gate_action(bundle, tool_name: "wire_transfer", args: { "amount" => 999 }, agent_id: "agent-1")
|
|
32
|
+
block_the_call unless d["allowed"]
|
|
33
|
+
|
|
34
|
+
# Gate a retrieval — drop on deny/escalate; redact via redactionRules.
|
|
35
|
+
r = Visiq.gate_retrieval(bundle, resource_metadata: { "classification" => "ssn" })
|
|
36
|
+
# r["retrieval"]["action"] ∈ allow | deny | redact | escalate
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
`Visiq.decide(event, bundle)` returns the full `UnifiedDecision` hash
|
|
40
|
+
(`{"decision","allowed","action","retrieval"}`).
|
|
41
|
+
|
|
42
|
+
## Overriding the core location
|
|
43
|
+
|
|
44
|
+
Set `VISIQ_CORE_LIB` to an absolute path to a `libvisiq_core` shared library to
|
|
45
|
+
override the bundled one (e.g. for local development against a fresh build).
|
|
46
|
+
|
|
47
|
+
## License
|
|
48
|
+
|
|
49
|
+
MIT © VisIQ Labs. See [LICENSE](./LICENSE).
|
data/lib/visiq.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# VisIQ agent-governance SDK (Ruby) — local, in-process policy decisions.
|
|
4
|
+
#
|
|
5
|
+
# ONE compiled Rust core (Path B) makes the SAME decisions as the shipped
|
|
6
|
+
# TypeScript SDK (`@visiq/harness`). This gem is a thin binding over the core's
|
|
7
|
+
# language-neutral C-ABI seam (`visiq_evaluate`/`visiq_free`) via Ruby's stdlib
|
|
8
|
+
# `Fiddle` — zero runtime gem dependencies. The engine is compiled machine code;
|
|
9
|
+
# the gem ships the shared library CLOSED (the Ruby is only FFI plumbing, no
|
|
10
|
+
# policy). Every decision is local (no network) and fails closed on malformed
|
|
11
|
+
# input (G001).
|
|
12
|
+
#
|
|
13
|
+
# require "visiq"
|
|
14
|
+
# d = Visiq.gate_action(bundle, tool_name: "wire_transfer", args: { "amount" => 999 }, agent_id: "a")
|
|
15
|
+
# block_the_call unless d["allowed"]
|
|
16
|
+
# r = Visiq.gate_retrieval(bundle, resource_metadata: { "classification" => "ssn" })
|
|
17
|
+
# # r["retrieval"]["action"] ∈ allow|deny|redact|escalate
|
|
18
|
+
require "fiddle"
|
|
19
|
+
require "json"
|
|
20
|
+
require "rbconfig"
|
|
21
|
+
|
|
22
|
+
module Visiq
|
|
23
|
+
VERSION = "0.1.0"
|
|
24
|
+
|
|
25
|
+
# Low-level binding to the compiled core over the C-ABI seam.
|
|
26
|
+
module Core
|
|
27
|
+
class << self
|
|
28
|
+
# JSON in, JSON out — the language-neutral FFI seam. Returns a heap C string
|
|
29
|
+
# the core allocates; we copy it into a Ruby String then hand it back to
|
|
30
|
+
# `visiq_free` so the core owns both sides of the allocation.
|
|
31
|
+
def evaluate_json(event_json, bundle_json)
|
|
32
|
+
ptr = evaluate_fn.call(event_json, bundle_json)
|
|
33
|
+
str = ptr.to_s
|
|
34
|
+
free_fn.call(ptr)
|
|
35
|
+
str
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def handle
|
|
41
|
+
@handle ||= begin
|
|
42
|
+
path = lib_path
|
|
43
|
+
Fiddle.dlopen(path)
|
|
44
|
+
rescue Fiddle::DLError => e
|
|
45
|
+
# A wrong-arch/OS bundled core (e.g. a forced install of a mismatched
|
|
46
|
+
# platform gem) fails to dlopen. Fail CLOSED with an actionable message,
|
|
47
|
+
# never a silent allow — the SDK cannot govern without its core (G001).
|
|
48
|
+
raise "visiq: failed to load the compiled core at #{path} for host " \
|
|
49
|
+
"#{RbConfig::CONFIG['host_cpu']}-#{RbConfig::CONFIG['host_os']} " \
|
|
50
|
+
"(#{e.message}). Install the platform-matching `visiq` gem, or set " \
|
|
51
|
+
"VISIQ_CORE_LIB to a compatible libvisiq_core."
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def evaluate_fn
|
|
56
|
+
@evaluate_fn ||= Fiddle::Function.new(
|
|
57
|
+
handle["visiq_evaluate"], [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOIDP
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def free_fn
|
|
62
|
+
@free_fn ||= Fiddle::Function.new(handle["visiq_free"], [Fiddle::TYPE_VOIDP], Fiddle::TYPE_VOID)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def lib_path
|
|
66
|
+
env = ENV["VISIQ_CORE_LIB"]
|
|
67
|
+
return env if env && File.exist?(env)
|
|
68
|
+
|
|
69
|
+
ext = case RbConfig::CONFIG["host_os"]
|
|
70
|
+
when /darwin/ then "dylib"
|
|
71
|
+
when /mswin|mingw/ then "dll"
|
|
72
|
+
else "so"
|
|
73
|
+
end
|
|
74
|
+
candidates = [
|
|
75
|
+
# bundled in the published gem (platform-specific), then the dev build:
|
|
76
|
+
File.join(__dir__, "..", "vendor", "libvisiq_core.#{ext}"),
|
|
77
|
+
File.join(__dir__, "..", "..", "visiq-core-rs", "target-capi", "release", "libvisiq_core.#{ext}")
|
|
78
|
+
]
|
|
79
|
+
found = candidates.find { |p| File.exist?(p) }
|
|
80
|
+
raise "visiq: cannot locate libvisiq_core.#{ext} (set VISIQ_CORE_LIB)" unless found
|
|
81
|
+
|
|
82
|
+
found
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
module_function
|
|
88
|
+
|
|
89
|
+
# Evaluate one governed agent event against a rules bundle. Returns the
|
|
90
|
+
# UnifiedDecision hash: {"decision","allowed","action","retrieval"}.
|
|
91
|
+
def decide(event, bundle)
|
|
92
|
+
JSON.parse(Core.evaluate_json(JSON.generate(event), JSON.generate(bundle)))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Gate a tool/action call. Check ["allowed"]; on "mask" apply
|
|
96
|
+
# ["action"]["argRedactionRules"] to the args before running the tool.
|
|
97
|
+
def gate_action(bundle, tool_name:, args: nil, agent_id: "agent", target_resource: nil, normalized: nil)
|
|
98
|
+
event = { "operations" => ["action"], "agentId" => agent_id, "toolName" => tool_name }
|
|
99
|
+
event["toolArgs"] = args unless args.nil?
|
|
100
|
+
event["targetResource"] = target_resource unless target_resource.nil?
|
|
101
|
+
event["normalized"] = normalized unless normalized.nil?
|
|
102
|
+
decide(event, bundle)
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
# Gate a retrieval. Inspect ["retrieval"]["action"] — drop on deny/escalate,
|
|
106
|
+
# redact via ["retrieval"]["redactionRules"] — before content reaches the model.
|
|
107
|
+
def gate_retrieval(bundle, resource_metadata: nil, resource_type: "document", agent_id: "agent", query: nil)
|
|
108
|
+
event = { "operations" => ["retrieval"], "agentId" => agent_id, "resourceType" => resource_type }
|
|
109
|
+
event["resourceMetadata"] = resource_metadata unless resource_metadata.nil?
|
|
110
|
+
event["query"] = query unless query.nil?
|
|
111
|
+
decide(event, bundle)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
Binary file
|
metadata
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: visiq
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: x86_64-linux
|
|
6
|
+
authors:
|
|
7
|
+
- VisIQ Labs Team
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2026-07-08 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: fiddle
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ">="
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.0'
|
|
27
|
+
description: ONE compiled Rust core (Path B) that reproduces the shipped TypeScript
|
|
28
|
+
SDK's decisions, bound to Ruby via a stdlib Fiddle FFI. Fully local; fails closed
|
|
29
|
+
on malformed input (G001). The engine ships as compiled machine code (closed); the
|
|
30
|
+
Ruby is thin FFI plumbing only.
|
|
31
|
+
email:
|
|
32
|
+
- dev@visiqlabs.com
|
|
33
|
+
executables: []
|
|
34
|
+
extensions: []
|
|
35
|
+
extra_rdoc_files: []
|
|
36
|
+
files:
|
|
37
|
+
- LICENSE
|
|
38
|
+
- README.md
|
|
39
|
+
- lib/visiq.rb
|
|
40
|
+
- vendor/libvisiq_core.so
|
|
41
|
+
homepage: https://docs.visiqlabs.com
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata:
|
|
45
|
+
rubygems_mfa_required: 'true'
|
|
46
|
+
allowed_push_host: https://rubygems.org
|
|
47
|
+
homepage_uri: https://docs.visiqlabs.com
|
|
48
|
+
documentation_uri: https://docs.visiqlabs.com
|
|
49
|
+
bug_tracker_uri: https://docs.visiqlabs.com/support
|
|
50
|
+
post_install_message:
|
|
51
|
+
rdoc_options: []
|
|
52
|
+
require_paths:
|
|
53
|
+
- lib
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '3.0'
|
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
requirements: []
|
|
65
|
+
rubygems_version: 3.5.22
|
|
66
|
+
signing_key:
|
|
67
|
+
specification_version: 4
|
|
68
|
+
summary: VisIQ agent-governance SDK — local, in-process policy decisions.
|
|
69
|
+
test_files: []
|