vella-sdk 1.0.1__tar.gz

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.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: vella-sdk
3
+ Version: 1.0.1
4
+ Summary: VELLA — deterministic pre-execution governance substrate. SDK for producing signed decision records.
5
+ Author-email: "Vella Cognitive, LLC" <agent@vellacognitive.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://vellacognitive.com/research/an-inspectable-substrate-for-ai-governance
8
+ Project-URL: Repository, https://github.com/vellacognitive/vella-substrate
9
+ Project-URL: Issues, https://github.com/vellacognitive/vella-substrate/issues
10
+ Keywords: vella,governance,ai-safety,pre-execution,policy,audit,proof-bundle
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: cryptography>=41.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: ruff; extra == "dev"
23
+ Requires-Dist: mypy; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+
26
+ # vella-sdk
27
+
28
+ Python SDK for deterministic pre-execution adjudication and signed proof-bundle generation.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install vella-sdk
34
+ ```
35
+
36
+ ## From source (development)
37
+
38
+ ```bash
39
+ python3 -m venv .venv
40
+ . .venv/bin/activate
41
+ python -m pip install --upgrade pip
42
+ pip install -e ".[dev]"
43
+ pytest
44
+ ruff check .
45
+ mypy --strict vella/
46
+ ```
47
+
48
+ ## Basic usage
49
+
50
+ ```python
51
+ from vella import govern
52
+
53
+ result = govern(
54
+ intent="EXECUTE_CHANGE",
55
+ evidence_mask=1,
56
+ )
57
+
58
+ print(result["decision"]) # ALLOWED | DENIED
59
+ print(result["reason_code"]) # reason code string
60
+ ```
61
+
62
+ ## With proof bundle
63
+
64
+ ```python
65
+ from vella import govern
66
+
67
+ signing_key = open("./proof-signing.pem", "r", encoding="utf-8").read()
68
+
69
+ result = govern(
70
+ intent="EXECUTE_CHANGE",
71
+ evidence_mask=1,
72
+ proof_signing_key=signing_key,
73
+ )
74
+
75
+ print(result["proof_bundle"]["kind"]) # vella_proof_bundle_v1
76
+ ```
77
+
78
+ ## When to use this SDK
79
+
80
+ This SDK runs VELLA in-process inside your Python application. It is the right choice for agent tool-call hooks, CI/CD gating, edge compute, research notebooks, batch processing, and any context where microsecond-latency adjudication is needed without a separate service.
81
+
82
+ For enterprise service mesh, polyglot environments (Go, Java, .NET), Kubernetes admission control, or multi-tenant deployments, a different VELLA component (the runtime service or sidecar adapter) is the better fit. See the full [deployment scope](../../DEPLOYMENT.md) in the repository root.
83
+
84
+ ## API
85
+
86
+ - `govern(intent, evidence_mask, authority_scope=None, policy_version=None, proof_signing_key=None)`
87
+ - Returns a dict with `decision`, `reason_code`, `latency_us`, and optional `proof_bundle`/`proof_error`
88
+
89
+ ## Reference docs
90
+
91
+ See the root repository docs for full protocol details:
92
+ - `spec/icd.md`
93
+ - `spec/schemas/proof.json`
94
+ - `verify/`
@@ -0,0 +1,69 @@
1
+ # vella-sdk
2
+
3
+ Python SDK for deterministic pre-execution adjudication and signed proof-bundle generation.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install vella-sdk
9
+ ```
10
+
11
+ ## From source (development)
12
+
13
+ ```bash
14
+ python3 -m venv .venv
15
+ . .venv/bin/activate
16
+ python -m pip install --upgrade pip
17
+ pip install -e ".[dev]"
18
+ pytest
19
+ ruff check .
20
+ mypy --strict vella/
21
+ ```
22
+
23
+ ## Basic usage
24
+
25
+ ```python
26
+ from vella import govern
27
+
28
+ result = govern(
29
+ intent="EXECUTE_CHANGE",
30
+ evidence_mask=1,
31
+ )
32
+
33
+ print(result["decision"]) # ALLOWED | DENIED
34
+ print(result["reason_code"]) # reason code string
35
+ ```
36
+
37
+ ## With proof bundle
38
+
39
+ ```python
40
+ from vella import govern
41
+
42
+ signing_key = open("./proof-signing.pem", "r", encoding="utf-8").read()
43
+
44
+ result = govern(
45
+ intent="EXECUTE_CHANGE",
46
+ evidence_mask=1,
47
+ proof_signing_key=signing_key,
48
+ )
49
+
50
+ print(result["proof_bundle"]["kind"]) # vella_proof_bundle_v1
51
+ ```
52
+
53
+ ## When to use this SDK
54
+
55
+ This SDK runs VELLA in-process inside your Python application. It is the right choice for agent tool-call hooks, CI/CD gating, edge compute, research notebooks, batch processing, and any context where microsecond-latency adjudication is needed without a separate service.
56
+
57
+ For enterprise service mesh, polyglot environments (Go, Java, .NET), Kubernetes admission control, or multi-tenant deployments, a different VELLA component (the runtime service or sidecar adapter) is the better fit. See the full [deployment scope](../../DEPLOYMENT.md) in the repository root.
58
+
59
+ ## API
60
+
61
+ - `govern(intent, evidence_mask, authority_scope=None, policy_version=None, proof_signing_key=None)`
62
+ - Returns a dict with `decision`, `reason_code`, `latency_us`, and optional `proof_bundle`/`proof_error`
63
+
64
+ ## Reference docs
65
+
66
+ See the root repository docs for full protocol details:
67
+ - `spec/icd.md`
68
+ - `spec/schemas/proof.json`
69
+ - `verify/`
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=69", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "vella-sdk"
7
+ version = "1.0.1"
8
+ description = "VELLA — deterministic pre-execution governance substrate. SDK for producing signed decision records."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [
13
+ { name = "Vella Cognitive, LLC", email = "agent@vellacognitive.com" }
14
+ ]
15
+ dependencies = [
16
+ "cryptography>=41.0"
17
+ ]
18
+ keywords = [
19
+ "vella",
20
+ "governance",
21
+ "ai-safety",
22
+ "pre-execution",
23
+ "policy",
24
+ "audit",
25
+ "proof-bundle"
26
+ ]
27
+ classifiers = [
28
+ "License :: OSI Approved :: MIT License",
29
+ "Programming Language :: Python :: 3",
30
+ "Programming Language :: Python :: 3.10",
31
+ "Programming Language :: Python :: 3.11",
32
+ "Programming Language :: Python :: 3.12",
33
+ "Topic :: Security",
34
+ "Topic :: Software Development :: Libraries :: Python Modules"
35
+ ]
36
+
37
+ [project.optional-dependencies]
38
+ dev = ["ruff", "mypy", "pytest"]
39
+
40
+ [project.urls]
41
+ Homepage = "https://vellacognitive.com/research/an-inspectable-substrate-for-ai-governance"
42
+ Repository = "https://github.com/vellacognitive/vella-substrate"
43
+ Issues = "https://github.com/vellacognitive/vella-substrate/issues"
44
+
45
+ [tool.setuptools.packages.find]
46
+ include = ["vella*"]
47
+
48
+ [tool.mypy]
49
+ strict = true
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,61 @@
1
+ from vella import govern
2
+
3
+
4
+ def test_execute_change_with_authn_is_allowed() -> None:
5
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1)
6
+ assert result["decision"] == "ALLOWED"
7
+ assert result["reason_code"] == "POLICY_SATISFIED"
8
+
9
+
10
+ def test_execute_change_without_evidence_is_denied() -> None:
11
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=0)
12
+ assert result["decision"] == "DENIED"
13
+ assert result["reason_code"] == "E_EVIDENCE_MISSING"
14
+
15
+
16
+ def test_escalate_with_authn_authz_is_allowed() -> None:
17
+ result = govern(intent="ESCALATE_PRIVILEGE", evidence_mask=3)
18
+ assert result["decision"] == "ALLOWED"
19
+ assert result["reason_code"] == "POLICY_SATISFIED"
20
+
21
+
22
+ def test_escalate_with_only_authn_is_denied() -> None:
23
+ result = govern(intent="ESCALATE_PRIVILEGE", evidence_mask=1)
24
+ assert result["decision"] == "DENIED"
25
+ assert result["reason_code"] == "E_EVIDENCE_MISSING"
26
+
27
+
28
+ def test_data_export_with_authn_authz_is_allowed() -> None:
29
+ result = govern(intent="DATA_EXPORT", evidence_mask=3)
30
+ assert result["decision"] == "ALLOWED"
31
+ assert result["reason_code"] == "POLICY_SATISFIED"
32
+
33
+
34
+ def test_unknown_intent_is_denied_fast() -> None:
35
+ result = govern(intent="UNKNOWN_INTENT", evidence_mask=15)
36
+ assert result["decision"] == "DENIED"
37
+ assert result["reason_code"] == "DENY_FAST"
38
+
39
+
40
+ def test_missing_intent_is_denied() -> None:
41
+ result = govern(intent="", evidence_mask=1)
42
+ assert result["decision"] == "DENIED"
43
+ assert result["reason_code"] == "E_INTENT_REQUIRED"
44
+
45
+
46
+ def test_policy_version_mismatch_is_denied() -> None:
47
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, policy_version="v99")
48
+ assert result["decision"] == "DENIED"
49
+ assert result["reason_code"] == "E_POLICY_VERSION_MISMATCH"
50
+
51
+
52
+ def test_unknown_authority_scope_is_denied_fast() -> None:
53
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, authority_scope="unknown")
54
+ assert result["decision"] == "DENIED"
55
+ assert result["reason_code"] == "DENY_FAST"
56
+
57
+
58
+ def test_symbolic_evidence_list_is_supported() -> None:
59
+ result = govern(intent="DATA_EXPORT", evidence_mask=["AUTHN", "AUTHZ"])
60
+ assert result["decision"] == "ALLOWED"
61
+ assert result["reason_code"] == "POLICY_SATISFIED"
@@ -0,0 +1,90 @@
1
+ import base64
2
+ import hashlib
3
+ import json
4
+ from pathlib import Path
5
+
6
+ from cryptography.hazmat.primitives import hashes, serialization
7
+ from cryptography.hazmat.primitives.asymmetric import ec
8
+ from cryptography.hazmat.primitives.asymmetric.utils import encode_dss_signature
9
+
10
+ from vella import govern
11
+
12
+ SIGNING_EXCLUDED = {
13
+ "envelope_hash",
14
+ "signature_alg",
15
+ "signature",
16
+ "sha256_bundle",
17
+ "key_id",
18
+ "kind",
19
+ "exported_at",
20
+ }
21
+
22
+
23
+ def _read_fixture(name: str) -> str:
24
+ return (Path(__file__).parent / "fixtures" / name).read_text(encoding="utf-8")
25
+
26
+
27
+ def test_proof_bundle_is_generated() -> None:
28
+ private_key = _read_fixture("test-signing-private.pem")
29
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, proof_signing_key=private_key)
30
+ proof_bundle = result.get("proof_bundle")
31
+ assert isinstance(proof_bundle, dict)
32
+ assert proof_bundle["kind"] == "vella_proof_bundle_v1"
33
+
34
+
35
+ def test_envelope_hash_verifies() -> None:
36
+ private_key = _read_fixture("test-signing-private.pem")
37
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, proof_signing_key=private_key)
38
+ proof_bundle = result["proof_bundle"]
39
+ assert isinstance(proof_bundle, dict)
40
+
41
+ envelope = {k: v for k, v in proof_bundle.items() if k not in SIGNING_EXCLUDED}
42
+ canonical_envelope = json.dumps(envelope, sort_keys=True, separators=(",", ":"))
43
+ expected_hash = f"sha256:{hashlib.sha256(canonical_envelope.encode('utf-8')).hexdigest()}"
44
+ assert proof_bundle["envelope_hash"] == expected_hash
45
+
46
+
47
+ def test_signature_verifies() -> None:
48
+ private_key = _read_fixture("test-signing-private.pem")
49
+ public_key_pem = _read_fixture("test-signing-public.pem")
50
+
51
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, proof_signing_key=private_key)
52
+ proof_bundle = result["proof_bundle"]
53
+ assert isinstance(proof_bundle, dict)
54
+
55
+ public_key = serialization.load_pem_public_key(public_key_pem.encode("utf-8"))
56
+ assert isinstance(public_key, ec.EllipticCurvePublicKey)
57
+
58
+ signature_bytes = base64.b64decode(str(proof_bundle["signature"]))
59
+ r_value = int.from_bytes(signature_bytes[:32], "big")
60
+ s_value = int.from_bytes(signature_bytes[32:], "big")
61
+ der_signature = encode_dss_signature(r_value, s_value)
62
+
63
+ public_key.verify(
64
+ der_signature,
65
+ str(proof_bundle["envelope_hash"]).encode("utf-8"),
66
+ ec.ECDSA(hashes.SHA256()),
67
+ )
68
+
69
+
70
+ def test_bundle_hash_verifies() -> None:
71
+ private_key = _read_fixture("test-signing-private.pem")
72
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1, proof_signing_key=private_key)
73
+ proof_bundle = result["proof_bundle"]
74
+ assert isinstance(proof_bundle, dict)
75
+
76
+ envelope = {k: v for k, v in proof_bundle.items() if k not in SIGNING_EXCLUDED}
77
+ bundle_for_hash = {
78
+ **envelope,
79
+ "envelope_hash": proof_bundle["envelope_hash"],
80
+ "signature_alg": proof_bundle["signature_alg"],
81
+ "signature": proof_bundle["signature"],
82
+ }
83
+ canonical_bundle = json.dumps(bundle_for_hash, sort_keys=True, separators=(",", ":"))
84
+ expected_hash = f"sha256:{hashlib.sha256(canonical_bundle.encode('utf-8')).hexdigest()}"
85
+ assert proof_bundle["sha256_bundle"] == expected_hash
86
+
87
+
88
+ def test_proof_bundle_absent_when_no_signing_key() -> None:
89
+ result = govern(intent="EXECUTE_CHANGE", evidence_mask=1)
90
+ assert "proof_bundle" not in result
@@ -0,0 +1,70 @@
1
+ """VELLA SDK — MIT License — Copyright (c) 2026 Vella Cognitive, LLC"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+
7
+ from .evaluator import create_evaluator
8
+ from .policy import DEFAULT_POLICY
9
+ from .proof import build_envelope, sign_bundle
10
+
11
+ __version__ = "1.0.1"
12
+
13
+ _EVALUATOR = create_evaluator(DEFAULT_POLICY)
14
+
15
+
16
+ def govern(
17
+ intent: str | None,
18
+ evidence_mask: object,
19
+ authority_scope: str | None = None,
20
+ policy_version: str | None = None,
21
+ proof_signing_key: str | bytes | None = None,
22
+ ) -> dict[str, object]:
23
+ start = time.monotonic_ns()
24
+
25
+ try:
26
+ result = _EVALUATOR.evaluate(
27
+ {
28
+ "intent_id": intent,
29
+ "evidence_mask": evidence_mask,
30
+ "authority_scope_id": authority_scope,
31
+ "policy_version": policy_version,
32
+ }
33
+ )
34
+ latency_us = (time.monotonic_ns() - start) // 1000
35
+ output: dict[str, object] = {
36
+ "decision": result["decision"],
37
+ "reason_code": result["reason_code"],
38
+ "latency_us": latency_us,
39
+ }
40
+
41
+ if proof_signing_key is not None:
42
+ try:
43
+ envelope = build_envelope(
44
+ {
45
+ "intent_id": intent,
46
+ "evidence_mask": evidence_mask,
47
+ "authority_scope_id": authority_scope,
48
+ "policy_version": policy_version,
49
+ },
50
+ result,
51
+ {
52
+ "policyVersion": _EVALUATOR.policy_version,
53
+ "authorityScope": authority_scope,
54
+ },
55
+ )
56
+ output["proof_bundle"] = sign_bundle(envelope, proof_signing_key)
57
+ except Exception as proof_error: # noqa: BLE001
58
+ output["proof_bundle"] = None
59
+ output["proof_error"] = str(proof_error)
60
+
61
+ return output
62
+ except Exception: # noqa: BLE001
63
+ return {
64
+ "decision": "DENIED",
65
+ "reason_code": "E_EVALUATOR_INTERNAL",
66
+ "latency_us": 0,
67
+ }
68
+
69
+
70
+ __all__ = ["govern", "DEFAULT_POLICY", "__version__"]
@@ -0,0 +1,211 @@
1
+ """VELLA SDK — MIT License — Copyright (c) 2026 Vella Cognitive, LLC"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from dataclasses import dataclass
7
+ from typing import Mapping
8
+
9
+ from .policy import DEFAULT_POLICY
10
+
11
+ Decision = dict[str, str]
12
+
13
+ DECISION_ALLOWED: Decision = {"decision": "ALLOWED", "reason_code": "POLICY_SATISFIED"}
14
+ DECISION_DENIED_FAST: Decision = {"decision": "DENIED", "reason_code": "DENY_FAST"}
15
+ DECISION_DENIED_INTENT_REQUIRED: Decision = {
16
+ "decision": "DENIED",
17
+ "reason_code": "E_INTENT_REQUIRED",
18
+ }
19
+ DECISION_DENIED_POLICY_VERSION: Decision = {
20
+ "decision": "DENIED",
21
+ "reason_code": "E_POLICY_VERSION_MISMATCH",
22
+ }
23
+ DECISION_DENIED_EVIDENCE: Decision = {
24
+ "decision": "DENIED",
25
+ "reason_code": "E_EVIDENCE_MISSING",
26
+ }
27
+
28
+
29
+ @dataclass(frozen=True)
30
+ class CompiledScope:
31
+ allow_unknown_intents: bool
32
+ default_required_mask: int
33
+ intent_rules: dict[str, int]
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class CompiledPolicy:
38
+ policy_version: str
39
+ default_scope: str
40
+ evidence_bits: dict[str, int]
41
+ scopes: dict[str, CompiledScope]
42
+
43
+
44
+ def _normalize_id(value: object | None) -> str:
45
+ if value is None:
46
+ return ""
47
+ return str(value).strip().upper()
48
+
49
+
50
+ def _parse_unsigned_int_strict(text: str) -> int:
51
+ if len(text) == 0:
52
+ return -1
53
+ value = 0
54
+ for ch in text:
55
+ code = ord(ch)
56
+ if code < 48 or code > 57:
57
+ return -1
58
+ value = (value * 10) + (code - 48)
59
+ if not math.isfinite(value):
60
+ return -1
61
+ return value & 0xFFFFFFFF
62
+
63
+
64
+ def to_evidence_mask(value: object, evidence_bits: Mapping[str, int]) -> int:
65
+ if isinstance(value, bool):
66
+ return 0
67
+
68
+ if isinstance(value, int):
69
+ return value & 0xFFFFFFFF
70
+
71
+ if isinstance(value, float) and math.isfinite(value):
72
+ return int(value) & 0xFFFFFFFF
73
+
74
+ if isinstance(value, str):
75
+ trimmed = value.strip()
76
+ numeric = _parse_unsigned_int_strict(trimmed)
77
+ if numeric >= 0:
78
+ return numeric & 0xFFFFFFFF
79
+ bit = evidence_bits.get(_normalize_id(trimmed))
80
+ return (bit & 0xFFFFFFFF) if bit is not None else 0
81
+
82
+ if isinstance(value, list):
83
+ mask = 0
84
+ for item in value:
85
+ bit = evidence_bits.get(_normalize_id(item))
86
+ if bit is not None:
87
+ mask |= bit
88
+ return mask & 0xFFFFFFFF
89
+
90
+ return 0
91
+
92
+
93
+ def _to_int(value: object, default: int = 0) -> int:
94
+ if isinstance(value, bool):
95
+ return default
96
+ if isinstance(value, int):
97
+ return value
98
+ if isinstance(value, float) and math.isfinite(value):
99
+ return int(value)
100
+ if isinstance(value, str):
101
+ parsed = _parse_unsigned_int_strict(value.strip())
102
+ if parsed >= 0:
103
+ return parsed
104
+ return default
105
+
106
+
107
+ def compile_policy(policy_input: Mapping[str, object] | None = None) -> CompiledPolicy:
108
+ policy = policy_input if policy_input is not None else DEFAULT_POLICY
109
+
110
+ raw_evidence = policy.get("evidenceBits")
111
+ evidence_bits: dict[str, int] = {}
112
+ if isinstance(raw_evidence, Mapping):
113
+ for key, value in raw_evidence.items():
114
+ if not isinstance(key, str):
115
+ continue
116
+ evidence_bits[key] = _to_int(value) & 0xFFFFFFFF
117
+
118
+ raw_scopes = policy.get("scopes")
119
+ scopes: dict[str, CompiledScope] = {}
120
+ if isinstance(raw_scopes, Mapping):
121
+ for scope_name_obj, scope_cfg_obj in raw_scopes.items():
122
+ if not isinstance(scope_name_obj, str):
123
+ continue
124
+ scope_name = scope_name_obj
125
+ scope_cfg = scope_cfg_obj if isinstance(scope_cfg_obj, Mapping) else {}
126
+
127
+ raw_intents = scope_cfg.get("intents")
128
+ intent_rules: dict[str, int] = {}
129
+ if isinstance(raw_intents, Mapping):
130
+ for intent_name_obj, intent_mask_obj in raw_intents.items():
131
+ if not isinstance(intent_name_obj, str):
132
+ continue
133
+ intent_name = _normalize_id(intent_name_obj)
134
+ if not intent_name:
135
+ continue
136
+ intent_rules[intent_name] = _to_int(intent_mask_obj) & 0xFFFFFFFF
137
+
138
+ allow_unknown = bool(scope_cfg.get("allowUnknownIntents") is True)
139
+ default_required = _to_int(scope_cfg.get("defaultRequiredMask"), 0) & 0xFFFFFFFF
140
+ scopes[scope_name] = CompiledScope(
141
+ allow_unknown_intents=allow_unknown,
142
+ default_required_mask=default_required,
143
+ intent_rules=intent_rules,
144
+ )
145
+
146
+ default_scope_obj = policy.get("defaultScope")
147
+ default_scope = str(default_scope_obj) if default_scope_obj is not None else "sdk_v1_default"
148
+
149
+ policy_version_obj = policy.get("policyVersion")
150
+ policy_version = str(policy_version_obj) if policy_version_obj is not None else "min-v1"
151
+
152
+ return CompiledPolicy(
153
+ policy_version=policy_version,
154
+ default_scope=default_scope,
155
+ evidence_bits=evidence_bits,
156
+ scopes=scopes,
157
+ )
158
+
159
+
160
+ class Evaluator:
161
+ def __init__(self, compiled_policy: CompiledPolicy) -> None:
162
+ self._compiled = compiled_policy
163
+ self._default_scope = compiled_policy.scopes.get(compiled_policy.default_scope)
164
+ self.policy_version = compiled_policy.policy_version
165
+
166
+ def evaluate(self, input_dict: Mapping[str, object] | None) -> Decision:
167
+ if input_dict is None:
168
+ return DECISION_DENIED_INTENT_REQUIRED
169
+
170
+ raw_intent = (
171
+ input_dict.get("intent_id")
172
+ or input_dict.get("intent")
173
+ or input_dict.get("action")
174
+ )
175
+ intent_id = _normalize_id(raw_intent)
176
+ if not intent_id:
177
+ return DECISION_DENIED_INTENT_REQUIRED
178
+
179
+ authority_scope_id = input_dict.get("authority_scope_id")
180
+ if authority_scope_id is None or authority_scope_id == "":
181
+ scope = self._default_scope
182
+ if scope is None:
183
+ return DECISION_DENIED_FAST
184
+ else:
185
+ scope = self._compiled.scopes.get(str(authority_scope_id))
186
+ if scope is None:
187
+ return DECISION_DENIED_FAST
188
+
189
+ required_mask = scope.intent_rules.get(intent_id)
190
+ if required_mask is None:
191
+ if not scope.allow_unknown_intents:
192
+ return DECISION_DENIED_FAST
193
+ required_mask = scope.default_required_mask
194
+
195
+ requested_policy_version = input_dict.get("policy_version")
196
+ if (
197
+ requested_policy_version is not None
198
+ and requested_policy_version != ""
199
+ and str(requested_policy_version) != self._compiled.policy_version
200
+ ):
201
+ return DECISION_DENIED_POLICY_VERSION
202
+
203
+ evidence_mask = to_evidence_mask(input_dict.get("evidence_mask"), self._compiled.evidence_bits)
204
+ if (evidence_mask & required_mask) != required_mask:
205
+ return DECISION_DENIED_EVIDENCE
206
+
207
+ return DECISION_ALLOWED
208
+
209
+
210
+ def create_evaluator(policy_input: Mapping[str, object] | None = None) -> Evaluator:
211
+ return Evaluator(compile_policy(policy_input))
@@ -0,0 +1,27 @@
1
+ """VELLA SDK — MIT License — Copyright (c) 2026 Vella Cognitive, LLC"""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import Final
6
+
7
+ DEFAULT_POLICY: Final[dict[str, object]] = {
8
+ "policyVersion": "min-v1",
9
+ "defaultScope": "sdk_v1_default",
10
+ "evidenceBits": {
11
+ "AUTHN": 1,
12
+ "AUTHZ": 2,
13
+ "FRESHNESS": 4,
14
+ "ATTESTATION": 8,
15
+ },
16
+ "scopes": {
17
+ "sdk_v1_default": {
18
+ "allowUnknownIntents": False,
19
+ "defaultRequiredMask": 1,
20
+ "intents": {
21
+ "EXECUTE_CHANGE": 1,
22
+ "ESCALATE_PRIVILEGE": 1 | 2,
23
+ "DATA_EXPORT": 1 | 2,
24
+ },
25
+ },
26
+ },
27
+ }
@@ -0,0 +1,99 @@
1
+ """VELLA SDK — MIT License — Copyright (c) 2026 Vella Cognitive, LLC"""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import hashlib
7
+ import json
8
+ import os
9
+ import struct
10
+ import time
11
+ from datetime import datetime, timezone
12
+
13
+ from cryptography.hazmat.primitives import hashes, serialization
14
+ from cryptography.hazmat.primitives.asymmetric import ec
15
+ from cryptography.hazmat.primitives.asymmetric import utils as asym_utils
16
+
17
+
18
+ def _uuidv7() -> str:
19
+ buffer = bytearray(os.urandom(16))
20
+ now_ms = int(time.time() * 1000)
21
+ timestamp_bytes = struct.pack(">Q", now_ms)
22
+ buffer[0:6] = timestamp_bytes[2:8]
23
+ buffer[6] = (buffer[6] & 0x0F) | 0x70
24
+ buffer[8] = (buffer[8] & 0x3F) | 0x80
25
+ hexed = buffer.hex()
26
+ return f"{hexed[:8]}-{hexed[8:12]}-{hexed[12:16]}-{hexed[16:20]}-{hexed[20:]}"
27
+
28
+
29
+ def _load_ec_private_key(signing_key_pem: str | bytes) -> ec.EllipticCurvePrivateKey:
30
+ key_bytes = signing_key_pem.encode("utf-8") if isinstance(signing_key_pem, str) else signing_key_pem
31
+ private_key = serialization.load_pem_private_key(key_bytes, password=None)
32
+ if not isinstance(private_key, ec.EllipticCurvePrivateKey):
33
+ raise ValueError("signing key must be an EC private key")
34
+ return private_key
35
+
36
+
37
+ def build_envelope(
38
+ intent_input: dict[str, object] | None,
39
+ decision_result: dict[str, str] | None,
40
+ context: dict[str, object] | None,
41
+ ) -> dict[str, object]:
42
+ request = intent_input if isinstance(intent_input, dict) else {}
43
+ decision = decision_result if isinstance(decision_result, dict) else {}
44
+ ctx = context if isinstance(context, dict) else {}
45
+
46
+ return {
47
+ "envelope_id": f"env_{_uuidv7()}",
48
+ "intent": request.get("intent_id") or request.get("intent") or request.get("action"),
49
+ "proposed": request.get("proposed"),
50
+ "authority_scope": ctx.get("authorityScope") or request.get("authority_scope_id") or "sdk_v1_default",
51
+ "evidence_mask": request.get("evidence_mask", 0),
52
+ "decision": decision.get("decision", "DENIED"),
53
+ "reason_code": decision.get("reason_code", "E_EVALUATOR_INTERNAL"),
54
+ "policy_version": ctx.get("policyVersion", "min-v1"),
55
+ "build_hash": ctx.get("buildHash", "unset"),
56
+ "timestamp": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
57
+ "ok": decision.get("decision") in ("ALLOWED", "DENIED"),
58
+ "external_effects": False,
59
+ }
60
+
61
+
62
+ def derive_key_id(signing_key_pem: str | bytes) -> str:
63
+ private_key = _load_ec_private_key(signing_key_pem)
64
+ public_der = private_key.public_key().public_bytes(
65
+ encoding=serialization.Encoding.DER,
66
+ format=serialization.PublicFormat.SubjectPublicKeyInfo,
67
+ )
68
+ return f"key_{hashlib.sha256(public_der).hexdigest()[:16]}"
69
+
70
+
71
+ def sign_bundle(envelope: dict[str, object], signing_key_pem: str | bytes) -> dict[str, object]:
72
+ canonical_envelope = json.dumps(envelope, sort_keys=True, separators=(",", ":"))
73
+ envelope_hash = f"sha256:{hashlib.sha256(canonical_envelope.encode('utf-8')).hexdigest()}"
74
+
75
+ private_key = _load_ec_private_key(signing_key_pem)
76
+ der_signature = private_key.sign(envelope_hash.encode("utf-8"), ec.ECDSA(hashes.SHA256()))
77
+ r_value, s_value = asym_utils.decode_dss_signature(der_signature)
78
+ signature_bytes = r_value.to_bytes(32, "big") + s_value.to_bytes(32, "big")
79
+ signature = base64.b64encode(signature_bytes).decode("utf-8")
80
+
81
+ bundle_for_hash = {
82
+ **envelope,
83
+ "envelope_hash": envelope_hash,
84
+ "signature_alg": "ecdsa-p256-sha256",
85
+ "signature": signature,
86
+ }
87
+ canonical_bundle = json.dumps(bundle_for_hash, sort_keys=True, separators=(",", ":"))
88
+ sha256_bundle = f"sha256:{hashlib.sha256(canonical_bundle.encode('utf-8')).hexdigest()}"
89
+
90
+ return {
91
+ **envelope,
92
+ "envelope_hash": envelope_hash,
93
+ "signature_alg": "ecdsa-p256-sha256",
94
+ "signature": signature,
95
+ "sha256_bundle": sha256_bundle,
96
+ "key_id": derive_key_id(signing_key_pem),
97
+ "kind": "vella_proof_bundle_v1",
98
+ "exported_at": datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"),
99
+ }
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: vella-sdk
3
+ Version: 1.0.1
4
+ Summary: VELLA — deterministic pre-execution governance substrate. SDK for producing signed decision records.
5
+ Author-email: "Vella Cognitive, LLC" <agent@vellacognitive.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://vellacognitive.com/research/an-inspectable-substrate-for-ai-governance
8
+ Project-URL: Repository, https://github.com/vellacognitive/vella-substrate
9
+ Project-URL: Issues, https://github.com/vellacognitive/vella-substrate/issues
10
+ Keywords: vella,governance,ai-safety,pre-execution,policy,audit,proof-bundle
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Topic :: Security
17
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
+ Requires-Python: >=3.10
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: cryptography>=41.0
21
+ Provides-Extra: dev
22
+ Requires-Dist: ruff; extra == "dev"
23
+ Requires-Dist: mypy; extra == "dev"
24
+ Requires-Dist: pytest; extra == "dev"
25
+
26
+ # vella-sdk
27
+
28
+ Python SDK for deterministic pre-execution adjudication and signed proof-bundle generation.
29
+
30
+ ## Install
31
+
32
+ ```bash
33
+ pip install vella-sdk
34
+ ```
35
+
36
+ ## From source (development)
37
+
38
+ ```bash
39
+ python3 -m venv .venv
40
+ . .venv/bin/activate
41
+ python -m pip install --upgrade pip
42
+ pip install -e ".[dev]"
43
+ pytest
44
+ ruff check .
45
+ mypy --strict vella/
46
+ ```
47
+
48
+ ## Basic usage
49
+
50
+ ```python
51
+ from vella import govern
52
+
53
+ result = govern(
54
+ intent="EXECUTE_CHANGE",
55
+ evidence_mask=1,
56
+ )
57
+
58
+ print(result["decision"]) # ALLOWED | DENIED
59
+ print(result["reason_code"]) # reason code string
60
+ ```
61
+
62
+ ## With proof bundle
63
+
64
+ ```python
65
+ from vella import govern
66
+
67
+ signing_key = open("./proof-signing.pem", "r", encoding="utf-8").read()
68
+
69
+ result = govern(
70
+ intent="EXECUTE_CHANGE",
71
+ evidence_mask=1,
72
+ proof_signing_key=signing_key,
73
+ )
74
+
75
+ print(result["proof_bundle"]["kind"]) # vella_proof_bundle_v1
76
+ ```
77
+
78
+ ## When to use this SDK
79
+
80
+ This SDK runs VELLA in-process inside your Python application. It is the right choice for agent tool-call hooks, CI/CD gating, edge compute, research notebooks, batch processing, and any context where microsecond-latency adjudication is needed without a separate service.
81
+
82
+ For enterprise service mesh, polyglot environments (Go, Java, .NET), Kubernetes admission control, or multi-tenant deployments, a different VELLA component (the runtime service or sidecar adapter) is the better fit. See the full [deployment scope](../../DEPLOYMENT.md) in the repository root.
83
+
84
+ ## API
85
+
86
+ - `govern(intent, evidence_mask, authority_scope=None, policy_version=None, proof_signing_key=None)`
87
+ - Returns a dict with `decision`, `reason_code`, `latency_us`, and optional `proof_bundle`/`proof_error`
88
+
89
+ ## Reference docs
90
+
91
+ See the root repository docs for full protocol details:
92
+ - `spec/icd.md`
93
+ - `spec/schemas/proof.json`
94
+ - `verify/`
@@ -0,0 +1,13 @@
1
+ README.md
2
+ pyproject.toml
3
+ tests/test_evaluator.py
4
+ tests/test_proof.py
5
+ vella/__init__.py
6
+ vella/evaluator.py
7
+ vella/policy.py
8
+ vella/proof.py
9
+ vella_sdk.egg-info/PKG-INFO
10
+ vella_sdk.egg-info/SOURCES.txt
11
+ vella_sdk.egg-info/dependency_links.txt
12
+ vella_sdk.egg-info/requires.txt
13
+ vella_sdk.egg-info/top_level.txt
@@ -0,0 +1,6 @@
1
+ cryptography>=41.0
2
+
3
+ [dev]
4
+ ruff
5
+ mypy
6
+ pytest
@@ -0,0 +1 @@
1
+ vella