zerynex-python 0.2.0__py3-none-any.whl

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,95 @@
1
+ {
2
+ "schema_version": 1,
3
+ "tool": "zerynex",
4
+ "rule_set_version": "1.0.0",
5
+ "scope": "Selected structural PCZT disclosure-policy observations only. No cryptographic proof, wallet, consensus or anonymity verification.",
6
+ "rules": [
7
+ {
8
+ "id": "PCZT-DUMMY-KEY",
9
+ "title": "Intermediate dummy signing key exposed",
10
+ "severity": "warning",
11
+ "category": "handoff",
12
+ "applies_to": [
13
+ "analysis",
14
+ "stage_comparison"
15
+ ],
16
+ "summary": "An accessible dummy spending key is present in an intermediate PCZT handoff."
17
+ },
18
+ {
19
+ "id": "PCZT-GLOBAL-METADATA",
20
+ "title": "Unreviewed global metadata",
21
+ "severity": "warning",
22
+ "category": "metadata",
23
+ "applies_to": [
24
+ "analysis",
25
+ "stage_comparison"
26
+ ],
27
+ "summary": "Global proprietary fields require an explicit disclosure review."
28
+ },
29
+ {
30
+ "id": "PCZT-RESTRICTED-DISCLOSURE",
31
+ "title": "Restricted handoff field present",
32
+ "severity": "warning",
33
+ "category": "handoff",
34
+ "applies_to": [
35
+ "analysis",
36
+ "stage_comparison"
37
+ ],
38
+ "summary": "The receiving role could see a field prohibited by a selected restrictive application policy."
39
+ },
40
+ {
41
+ "id": "PCZT-SAPLING-POLICY",
42
+ "title": "Sapling components denied by policy",
43
+ "severity": "warning",
44
+ "category": "pool_policy",
45
+ "applies_to": [
46
+ "analysis",
47
+ "stage_comparison"
48
+ ],
49
+ "summary": "Sapling components exist despite an opt-in application restriction; Sapling itself is not prohibited by Zcash consensus."
50
+ },
51
+ {
52
+ "id": "PCZT-STRUCTURE-DRIFT",
53
+ "title": "PCZT component count changed",
54
+ "severity": "error",
55
+ "category": "regression",
56
+ "applies_to": [
57
+ "stage_comparison"
58
+ ],
59
+ "summary": "A covered component count changed between intermediate stages; values and cryptographic equivalence are not compared."
60
+ },
61
+ {
62
+ "id": "PCZT-TRANSPARENT-INPUTS",
63
+ "title": "Transparent inputs denied by policy",
64
+ "severity": "warning",
65
+ "category": "pool_policy",
66
+ "applies_to": [
67
+ "analysis",
68
+ "stage_comparison"
69
+ ],
70
+ "summary": "Transparent inputs were found while the selected policy denies transparent components."
71
+ },
72
+ {
73
+ "id": "PCZT-TRANSPARENT-OUTPUTS",
74
+ "title": "Transparent outputs denied by policy",
75
+ "severity": "warning",
76
+ "category": "pool_policy",
77
+ "applies_to": [
78
+ "analysis",
79
+ "stage_comparison"
80
+ ],
81
+ "summary": "Transparent outputs were found while the selected policy denies transparent components."
82
+ },
83
+ {
84
+ "id": "PCZT-UNREVIEWED-METADATA",
85
+ "title": "Unreviewed component metadata",
86
+ "severity": "warning",
87
+ "category": "metadata",
88
+ "applies_to": [
89
+ "analysis",
90
+ "stage_comparison"
91
+ ],
92
+ "summary": "Proprietary input, output or action fields are present and require disclosure review."
93
+ }
94
+ ]
95
+ }
Binary file
@@ -0,0 +1,87 @@
1
+ {
2
+ "version": 1,
3
+ "methods": [
4
+ {
5
+ "name": "rpc.discover",
6
+ "params": []
7
+ },
8
+ {
9
+ "name": "pczt_create",
10
+ "params": [
11
+ {
12
+ "name": "from",
13
+ "required": true
14
+ },
15
+ {
16
+ "name": "amounts",
17
+ "required": true
18
+ },
19
+ {
20
+ "name": "minconf",
21
+ "required": false
22
+ },
23
+ {
24
+ "name": "privacy_policy",
25
+ "required": false
26
+ },
27
+ {
28
+ "name": "fund_source",
29
+ "required": false
30
+ }
31
+ ]
32
+ },
33
+ {
34
+ "name": "pczt_combine",
35
+ "params": [
36
+ {
37
+ "name": "pczts",
38
+ "required": true
39
+ }
40
+ ]
41
+ },
42
+ {
43
+ "name": "pczt_inspect",
44
+ "params": [
45
+ {
46
+ "name": "pczt",
47
+ "required": true
48
+ }
49
+ ]
50
+ },
51
+ {
52
+ "name": "pczt_prove",
53
+ "params": [
54
+ {
55
+ "name": "pczt",
56
+ "required": true
57
+ }
58
+ ]
59
+ },
60
+ {
61
+ "name": "pczt_sign",
62
+ "params": [
63
+ {
64
+ "name": "pczt",
65
+ "required": true
66
+ },
67
+ {
68
+ "name": "privacy_policy",
69
+ "required": false
70
+ },
71
+ {
72
+ "name": "strict",
73
+ "required": false
74
+ }
75
+ ]
76
+ },
77
+ {
78
+ "name": "pczt_extract",
79
+ "params": [
80
+ {
81
+ "name": "pczt",
82
+ "required": true
83
+ }
84
+ ]
85
+ }
86
+ ]
87
+ }
@@ -0,0 +1,127 @@
1
+ {
2
+ "openrpc": "1.3.2",
3
+ "info": {
4
+ "title": "Synthetic PCZT lifecycle schema - NOT a Zallet release snapshot",
5
+ "version": "synthetic"
6
+ },
7
+ "methods": [
8
+ {
9
+ "name": "rpc.discover",
10
+ "params": []
11
+ },
12
+ {
13
+ "name": "pczt_create",
14
+ "params": [
15
+ {
16
+ "name": "from",
17
+ "required": true,
18
+ "schema": {
19
+ "type": "string"
20
+ }
21
+ },
22
+ {
23
+ "name": "amounts",
24
+ "required": true,
25
+ "schema": {
26
+ "type": "array"
27
+ }
28
+ },
29
+ {
30
+ "name": "minconf",
31
+ "required": false,
32
+ "schema": {
33
+ "type": "number"
34
+ }
35
+ },
36
+ {
37
+ "name": "privacy_policy",
38
+ "required": false,
39
+ "schema": {
40
+ "type": "string"
41
+ }
42
+ },
43
+ {
44
+ "name": "fund_source",
45
+ "required": false,
46
+ "schema": {
47
+ "type": "string"
48
+ }
49
+ }
50
+ ]
51
+ },
52
+ {
53
+ "name": "pczt_combine",
54
+ "params": [
55
+ {
56
+ "name": "pczts",
57
+ "required": true,
58
+ "schema": {
59
+ "type": "array"
60
+ }
61
+ }
62
+ ]
63
+ },
64
+ {
65
+ "name": "pczt_inspect",
66
+ "params": [
67
+ {
68
+ "name": "pczt",
69
+ "required": true,
70
+ "schema": {
71
+ "type": "string"
72
+ }
73
+ }
74
+ ]
75
+ },
76
+ {
77
+ "name": "pczt_prove",
78
+ "params": [
79
+ {
80
+ "name": "pczt",
81
+ "required": true,
82
+ "schema": {
83
+ "type": "string"
84
+ }
85
+ }
86
+ ]
87
+ },
88
+ {
89
+ "name": "pczt_sign",
90
+ "params": [
91
+ {
92
+ "name": "pczt",
93
+ "required": true,
94
+ "schema": {
95
+ "type": "string"
96
+ }
97
+ },
98
+ {
99
+ "name": "privacy_policy",
100
+ "required": false,
101
+ "schema": {
102
+ "type": "string"
103
+ }
104
+ },
105
+ {
106
+ "name": "strict",
107
+ "required": false,
108
+ "schema": {
109
+ "type": "boolean"
110
+ }
111
+ }
112
+ ]
113
+ },
114
+ {
115
+ "name": "pczt_extract",
116
+ "params": [
117
+ {
118
+ "name": "pczt",
119
+ "required": true,
120
+ "schema": {
121
+ "type": "string"
122
+ }
123
+ }
124
+ ]
125
+ }
126
+ ]
127
+ }
@@ -0,0 +1,152 @@
1
+ """Verify a REAL local MCP stdio connection and Rust-backed synthetic suite.
2
+
3
+ A standalone diagnostic; never reads or prints transaction contents. No
4
+ HTTP service, provider account or AI model is involved.
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ import asyncio
10
+ import json
11
+ import os
12
+ from pathlib import Path
13
+ import shutil
14
+ import sys
15
+
16
+
17
+ async def check(server: Path, cli: Path, fixtures: Path) -> dict[str, object]:
18
+ try:
19
+ from mcp import Client
20
+ from mcp.client.stdio import StdioServerParameters
21
+ except ImportError:
22
+ raise RuntimeError("Install the optional MCP Python SDK before running the doctor.") from None
23
+
24
+ params = StdioServerParameters(
25
+ command=str(server),
26
+ args=[],
27
+ env={
28
+ "ZERYNEX_CLI": str(cli),
29
+ "ZERYNEX_AGENT_ALLOWED_ROOT": str(fixtures),
30
+ },
31
+ )
32
+ async with Client(params, raise_exceptions=True, read_timeout_seconds=35) as agent:
33
+ tools = await agent.list_tools()
34
+ names = sorted(tool.name for tool in tools.tools)
35
+ needed = {
36
+ "analyze_synthetic_pczt",
37
+ "compare_synthetic_pczt_stages",
38
+ "list_synthetic_fixtures",
39
+ "explain_zerynex_rule",
40
+ "run_synthetic_smoke_suite",
41
+ "zerynex_policy_schema",
42
+ "zerynex_core_capabilities",
43
+ "zerynex_rule_catalog",
44
+ "check_synthetic_zallet_rpc_contract",
45
+ "run_zerynex_developer_preflight",
46
+ "audit_synthetic_refund_privacy",
47
+ "compare_synthetic_refund_privacy",
48
+ }
49
+ if not needed.issubset(names):
50
+ raise RuntimeError("Local server does not expose all expected MCP capabilities.")
51
+ registry = await agent.call_tool("zerynex_rule_catalog", {})
52
+ rule_data = registry.structured_content
53
+ if not isinstance(rule_data, dict):
54
+ from mcp.types import TextContent
55
+ blocks = [item for item in registry.content if isinstance(item, TextContent)]
56
+ rule_data = json.loads(blocks[0].text) if len(blocks) == 1 else None
57
+ if not isinstance(rule_data, dict) or rule_data.get("rule_set_version") != "1.0.0" or len(rule_data.get("rules", [])) != 8:
58
+ raise RuntimeError("Installed Rust rule registry and bundled SDK are incompatible.")
59
+ suite = await agent.call_tool("run_synthetic_smoke_suite", {})
60
+ result = suite.structured_content
61
+ # Some supported protocol versions return text blocks instead.
62
+ if not isinstance(result, dict):
63
+ from mcp.types import TextContent
64
+ blocks = [item for item in suite.content if isinstance(item, TextContent)]
65
+ if len(blocks) != 1:
66
+ raise RuntimeError("Invalid structured response from the MCP tool.")
67
+ result = json.loads(blocks[0].text)
68
+ if not isinstance(result, dict):
69
+ raise RuntimeError("Invalid synthetic suite response.")
70
+ ok = result.get("passed") is True and result.get("total") == 4 and result.get("matched") == 4
71
+ readiness = await agent.call_tool("run_zerynex_developer_preflight", {})
72
+ preflight = readiness.structured_content
73
+ if not isinstance(preflight, dict):
74
+ from mcp.types import TextContent
75
+ blocks = [item for item in readiness.content if isinstance(item, TextContent)]
76
+ preflight = json.loads(blocks[0].text) if len(blocks) == 1 else None
77
+ if not isinstance(preflight, dict):
78
+ raise RuntimeError("Invalid developer preflight response.")
79
+ regression = await agent.call_tool("check_synthetic_zallet_rpc_contract", {"scenario": "new_required_parameter"})
80
+ drift = regression.structured_content
81
+ if not isinstance(drift, dict):
82
+ from mcp.types import TextContent
83
+ blocks = [item for item in regression.content if isinstance(item, TextContent)]
84
+ drift = json.loads(blocks[0].text) if len(blocks) == 1 else None
85
+ if not isinstance(drift, dict):
86
+ raise RuntimeError("Invalid regression response.")
87
+ safe_case = await agent.call_tool("audit_synthetic_refund_privacy", {"scenario": "isolated"})
88
+ unsafe_case = await agent.call_tool("audit_synthetic_refund_privacy", {"scenario": "risky"})
89
+ delta = await agent.call_tool("compare_synthetic_refund_privacy",
90
+ {"baseline": "risky", "candidate": "regression-expanded"})
91
+ def content_data(value):
92
+ data = value.structured_content
93
+ if not isinstance(data, dict):
94
+ from mcp.types import TextContent
95
+ blocks = [item for item in value.content if isinstance(item, TextContent)]
96
+ data = json.loads(blocks[0].text) if len(blocks) == 1 else None
97
+ return data if isinstance(data, dict) else {}
98
+ refund_ready = (content_data(safe_case).get("report", {}).get("passed") is True
99
+ and content_data(unsafe_case).get("report", {}).get("finding_count") == 5
100
+ and content_data(delta).get("report", {}).get("new_risk_events") == 1
101
+ and preflight.get("checks", {}).get("synthetic_refund_privacy", {}).get("matched") == 6)
102
+ ready = preflight.get("passed") is True and preflight.get("synthetic_only") is True
103
+ negative = (drift.get("contract_passed") is False and drift.get("matched_expectation") is True
104
+ and drift.get("finding_count") == 1)
105
+ return {
106
+ "connected": True,
107
+ "tool_count": len(names),
108
+ "tools": names,
109
+ "suite_passed": ok,
110
+ "suite_matched": result.get("matched", 0),
111
+ "suite_total": result.get("total", 4),
112
+ "preflight_passed": ready,
113
+ "rpc_regression_detected": negative,
114
+ "refund_privacy_verified": refund_ready,
115
+ "note": "MCP stdio subprocess and real Rust CLI. Synthetic inputs only.",
116
+ }
117
+
118
+
119
+ def main() -> None:
120
+ parser = argparse.ArgumentParser(description="Check a local Zerynex MCP server against synthetic fixtures.")
121
+ parser.add_argument("--cli", default=os.environ.get("ZERYNEX_CLI", ""), help="Absolute path to the trusted Rust CLI")
122
+ parser.add_argument("--fixtures", default=os.environ.get("ZERYNEX_AGENT_ALLOWED_ROOT", ""), help="Absolute synthetic-only fixture directory")
123
+ parser.add_argument("--server", default=shutil.which("zerynex-mcp") or "", help="Absolute path to local zerynex-mcp executable")
124
+ parser.add_argument("--json", action="store_true", help="Print a sanitized JSON outcome")
125
+ args = parser.parse_args()
126
+ # Avoid including user paths in errors, logs, and diagnostic output.
127
+ if not args.cli or not args.fixtures or not args.server:
128
+ parser.error("Provide --cli, --fixtures and --server for an explicit local setup.")
129
+ try:
130
+ cli, fixtures, server = (Path(path).expanduser().resolve(strict=True)
131
+ for path in (args.cli, args.fixtures, args.server))
132
+ if not cli.is_file() or not server.is_file() or not fixtures.is_dir():
133
+ raise RuntimeError("Invalid configured local paths.")
134
+ report = asyncio.run(check(server, cli, fixtures))
135
+ except Exception: # MCP transport can raise ExceptionGroup; always redact errors.
136
+ print("Zerynex MCP connection or synthetic suite failed. Check local setup.", file=sys.stderr)
137
+ raise SystemExit(1) from None
138
+ if args.json:
139
+ print(json.dumps(report, indent=2))
140
+ else:
141
+ print("MCP stdio: connected")
142
+ print("Discovered tools:", report["tool_count"])
143
+ print("Synthetic Rust checks:", str(report["suite_matched"]) + "/" + str(report["suite_total"]))
144
+ print("Developer preflight:", "PASS" if report["preflight_passed"] else "FAIL")
145
+ print("Synthetic RPC drift detected:", "YES" if report["rpc_regression_detected"] else "NO")
146
+ print("Synthetic refund privacy:", "PASS" if report["refund_privacy_verified"] else "FAIL")
147
+ print("Result:", "PASS" if report["suite_passed"] and report["preflight_passed"] and report["rpc_regression_detected"] and report["refund_privacy_verified"] else "FAIL")
148
+ raise SystemExit(0 if report["suite_passed"] and report["preflight_passed"] and report["rpc_regression_detected"] and report["refund_privacy_verified"] else 2)
149
+
150
+
151
+ if __name__ == "__main__":
152
+ main()