@obelyzk/sdk 1.4.0 → 1.6.0

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,112 @@
1
+ #!/usr/bin/env bash
2
+ # ObelyZK PreToolUse Hook
3
+ #
4
+ # Claude Code hook that intercepts tool calls and classifies on-chain
5
+ # transactions before execution using the ZKML classifier.
6
+ #
7
+ # Install in .claude/settings.json:
8
+ # {
9
+ # "hooks": {
10
+ # "PreToolUse": [{
11
+ # "matcher": "Bash",
12
+ # "hooks": [{
13
+ # "type": "command",
14
+ # "command": "/path/to/pre-tool-use.sh"
15
+ # }]
16
+ # }]
17
+ # }
18
+ # }
19
+ #
20
+ # Environment:
21
+ # PROVER_URL - Prove-server base URL (default: http://localhost:8080)
22
+ #
23
+ # Exit behavior:
24
+ # Outputs JSON to stdout. Exit 0 always (fail-open).
25
+ # When classifier uses test weights, only warns — never blocks.
26
+
27
+ set -euo pipefail
28
+
29
+ PROVER_URL="${PROVER_URL:-http://localhost:8080}"
30
+ CLASSIFY_TIMEOUT=5
31
+
32
+ # Read hook context from stdin
33
+ INPUT=$(cat)
34
+
35
+ TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty' 2>/dev/null || echo "")
36
+ if [ -z "$TOOL_NAME" ]; then
37
+ exit 0
38
+ fi
39
+
40
+ # Only intercept Bash tool
41
+ if [ "$TOOL_NAME" != "Bash" ]; then
42
+ exit 0
43
+ fi
44
+
45
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty' 2>/dev/null || echo "")
46
+ if [ -z "$COMMAND" ]; then
47
+ exit 0
48
+ fi
49
+
50
+ # Match on-chain transaction patterns
51
+ if ! echo "$COMMAND" | grep -qE '(starkli invoke|starkli deploy|sncast invoke|sncast deploy)'; then
52
+ exit 0
53
+ fi
54
+
55
+ # Extract the first hex address from the command (target contract)
56
+ TARGET=$(echo "$COMMAND" | grep -oE '0x[0-9a-fA-F]{10,66}' | head -1 || echo "")
57
+ if [ -z "$TARGET" ]; then
58
+ exit 0
59
+ fi
60
+
61
+ # Classify the transaction
62
+ RESULT=$(curl -s --max-time "$CLASSIFY_TIMEOUT" \
63
+ -X POST "${PROVER_URL}/api/v1/classify" \
64
+ -H "Content-Type: application/json" \
65
+ -d "{\"target\": \"$TARGET\", \"value\": \"0\", \"selector\": \"0x0\"}" \
66
+ 2>/dev/null || echo '{"error": "prover_unreachable"}')
67
+
68
+ # Check for errors
69
+ ERROR=$(echo "$RESULT" | jq -r '.error // empty' 2>/dev/null || echo "")
70
+ if [ -n "$ERROR" ]; then
71
+ # Fail-open: prover unreachable or error, allow the action
72
+ echo "ObelyZK: prover unreachable or error ($ERROR), allowing action" >&2
73
+ exit 0
74
+ fi
75
+
76
+ DECISION=$(echo "$RESULT" | jq -r '.decision // "approve"' 2>/dev/null || echo "approve")
77
+ SCORE=$(echo "$RESULT" | jq -r '.threat_score // 0' 2>/dev/null || echo "0")
78
+ PROOF_HASH=$(echo "$RESULT" | jq -r '.io_commitment // "unknown"' 2>/dev/null || echo "unknown")
79
+
80
+ # Log classification result to stderr (visible in Claude Code logs)
81
+ echo "ObelyZK classify: target=$TARGET decision=$DECISION threat_score=$SCORE" >&2
82
+
83
+ case "$DECISION" in
84
+ block)
85
+ # With test weights, warn but don't block
86
+ echo "ObelyZK: WOULD BLOCK (test weights active). threat_score=$SCORE proof=$PROOF_HASH" >&2
87
+ # When trained weights are deployed, uncomment the following to enforce:
88
+ # jq -n --arg reason "ObelyZK Firewall: transaction blocked (threat_score=$SCORE). Proof: $PROOF_HASH" '{
89
+ # hookSpecificOutput: {
90
+ # hookEventName: "PreToolUse",
91
+ # permissionDecision: "deny",
92
+ # permissionDecisionReason: $reason
93
+ # }
94
+ # }'
95
+ exit 0
96
+ ;;
97
+ escalate)
98
+ # Ask the user for confirmation
99
+ jq -n --arg reason "ObelyZK Firewall: transaction flagged (threat_score=$SCORE, target=$TARGET). Review before proceeding." '{
100
+ hookSpecificOutput: {
101
+ hookEventName: "PreToolUse",
102
+ permissionDecision: "ask",
103
+ permissionDecisionReason: $reason
104
+ }
105
+ }'
106
+ exit 0
107
+ ;;
108
+ *)
109
+ # Approved — allow
110
+ exit 0
111
+ ;;
112
+ esac
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # ObelyZK SessionStart Policy Hook
3
+ #
4
+ # Loads and displays the active policy configuration at session start.
5
+ # Shows the current preset, commitment hash, and enforcement mode so
6
+ # the agent knows what rules are active before taking any actions.
7
+ #
8
+ # Install in .claude/settings.json:
9
+ # {
10
+ # "hooks": {
11
+ # "SessionStart": [{
12
+ # "hooks": [{
13
+ # "type": "command",
14
+ # "command": "/path/to/session-start.sh"
15
+ # }]
16
+ # }]
17
+ # }
18
+ # }
19
+ #
20
+ # Environment:
21
+ # PROVER_URL - Prove-server base URL (default: http://localhost:8080)
22
+
23
+ set -euo pipefail
24
+
25
+ PROVER_URL="${PROVER_URL:-http://localhost:8080}"
26
+
27
+ # Try to reach the prover and get health info
28
+ HEALTH=$(curl -s --max-time 3 "${PROVER_URL}/health" 2>/dev/null || echo '{}')
29
+
30
+ if [ "$HEALTH" = "{}" ]; then
31
+ echo "ObelyZK Policy: prover unreachable at ${PROVER_URL}" >&2
32
+ echo " Classification will be unavailable until the prover is running." >&2
33
+ exit 0
34
+ fi
35
+
36
+ GPU=$(echo "$HEALTH" | jq -r '.gpu // "unknown"' 2>/dev/null || echo "unknown")
37
+ UPTIME=$(echo "$HEALTH" | jq -r '.uptime_s // "unknown"' 2>/dev/null || echo "unknown")
38
+ MODELS=$(echo "$HEALTH" | jq -r '.models_loaded // "unknown"' 2>/dev/null || echo "unknown")
39
+
40
+ echo "ObelyZK Policy Enforcement Active" >&2
41
+ echo " Prover: ${PROVER_URL} (GPU: ${GPU}, uptime: ${UPTIME}s)" >&2
42
+ echo " Models: ${MODELS}" >&2
43
+ echo " Classifier: test weights (NOT trained — decisions are non-meaningful)" >&2
44
+ echo " Policy: standard (commitment enabled)" >&2
45
+ echo " Thresholds: approve <40K | escalate 40-70K | block >70K" >&2
46
+ echo "" >&2
47
+ echo " All on-chain actions will be classified before execution." >&2
48
+ echo " Use firewall_health tool for detailed status." >&2
49
+
50
+ exit 0