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.
Files changed (6) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +49 -0
  4. data/lib/visiq.rb +113 -0
  5. data/vendor/libvisiq_core.so +0 -0
  6. 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: []